国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java集合問(wèn)題大匯總

894974231 / 1730人閱讀

摘要:集合中成員很豐富,常用的集合有,,等。實(shí)現(xiàn)接口的集合主要有。集合中不能包含重復(fù)的元素,每個(gè)元素必須是唯一的。而以作為實(shí)現(xiàn)的構(gòu)造函數(shù)的訪問(wèn)權(quán)限是默認(rèn)訪問(wèn)權(quán)限,即包內(nèi)訪問(wèn)權(quán)限。與接口不同,它是由一系列鍵值對(duì)組成的集合,提供了到的映射。

原文地址

Java集合

Java集合框架:是一種工具類,就像是一個(gè)容器可以存儲(chǔ)任意數(shù)量的具有共同屬性的對(duì)象。

Java集合中成員很豐富,常用的集合有ArrayList,HashMap,HashSet等。線程安全的有Vector,HashTable。線程不安全的有LinkedList,TreeMap,ArrayList,HashMap等等。

集合中用到的數(shù)據(jù)結(jié)構(gòu)有以下幾種:

數(shù)組:最常用的數(shù)據(jù)結(jié)構(gòu)之一。數(shù)組的特點(diǎn)是長(zhǎng)度固定,可以用下標(biāo)索引,并且所有的元素的類型都是一致的。使用時(shí)盡量把數(shù)組封裝在一個(gè)類里,防止數(shù)據(jù)被錯(cuò)誤的操作弄亂。

鏈表:是一種由多個(gè)節(jié)點(diǎn)組成的數(shù)據(jù)結(jié)構(gòu),并且每個(gè)節(jié)點(diǎn)包含有數(shù)據(jù)以及指向下一個(gè)節(jié)點(diǎn)的引用,在雙向鏈表里,還會(huì)有一個(gè)指向前一個(gè)節(jié)點(diǎn)的引用。例如,可以用單向鏈表和雙向鏈表來(lái)實(shí)現(xiàn)堆棧和隊(duì)列,因?yàn)殒湵淼膬啥硕际强梢赃M(jìn)行插入和刪除的動(dòng)作的。當(dāng)然,也會(huì)有在鏈表的中間頻繁插入和刪除節(jié)點(diǎn)的場(chǎng)景。

樹(shù):是一種由節(jié)點(diǎn)組成的數(shù)據(jù)結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都包含數(shù)據(jù)元素,并且有一個(gè)或多個(gè)子節(jié)點(diǎn),每個(gè)子節(jié)點(diǎn)指向一個(gè)父節(jié)點(diǎn)可以表示層級(jí)關(guān)系或者數(shù)據(jù)元素的順序關(guān)系。如果樹(shù)的每個(gè)子節(jié)點(diǎn)最多有兩個(gè)葉子節(jié)點(diǎn),那么這種樹(shù)被稱為二叉樹(shù)。二叉樹(shù)是一種非常常用的樹(shù)形結(jié)構(gòu), 因?yàn)樗倪@種結(jié)構(gòu)使得節(jié)點(diǎn)的插入和刪除都非常高效。樹(shù)的邊表示從一個(gè)節(jié)點(diǎn)到另外一個(gè)節(jié)點(diǎn)的快捷路徑。

堆棧:只允許對(duì)最后插入的元素進(jìn)行操作(也就是后進(jìn)先出,Last In First Out – LIFO)。如果你移除了棧頂?shù)脑兀敲茨憧梢圆僮鞯箶?shù)第二個(gè)元素,依次類推。這種后進(jìn)先出的方式是通過(guò)僅有的peek(),push()和pop()這幾個(gè)方法的強(qiáng)制性限制達(dá)到的。這種結(jié)構(gòu)在很多場(chǎng)景下都非常實(shí)用,例如解析像(4+2)*3這樣的數(shù)學(xué)表達(dá)式,把源碼中的方法和異常按照他們出現(xiàn)的順序放到堆棧中,檢查你的代碼看看小括號(hào)和花括號(hào)是不是匹配的,等等。

隊(duì)列:和堆棧有些相似,不同之處在于在隊(duì)列里第一個(gè)插入的元素也是第一個(gè)被刪除的元素(即是先進(jìn)先出)。這種先進(jìn)先出的結(jié)構(gòu)是通過(guò)只提供peek(),offer()和poll()這幾個(gè)方法來(lái)訪問(wèn)數(shù)據(jù)進(jìn)行限制來(lái)達(dá)到的。例如,排隊(duì)等待公交車,銀行或者超市里的等待列隊(duì)等等,都是可以用隊(duì)列來(lái)表示。

Java集合框架圖

[圖片上傳失敗...(image-4b8b54-1530872801038)]

Collection interface

如上圖所示,Collection接口是最基本的集合接口,它不提供直接的實(shí)現(xiàn),Java SDK提供的類都是繼承自Collection的“子接口”如List,Set和Queue。Collection所代表的是一種規(guī)則,它所包含的元素都必須遵循一條或者多條規(guī)則。如有些允許出現(xiàn)重復(fù)元素而有些則不允許重復(fù)、有些必須要按照順序插入而有些則是散列,有些支持排序但是有些則不支持等等。

List

List接口是Collection接口下的子接口。List所代表的是有序的Collection,即它用某種特定的插入順序來(lái)維護(hù)元素順序。用戶可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制,同時(shí)可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問(wèn)元素,并搜索列表中的元素。實(shí)現(xiàn)List接口的集合主要有:ArrayList、LinkedList、Vector、Stack。

ArrayList

ArrayList基于數(shù)組實(shí)現(xiàn),可以通過(guò)下標(biāo)索引直接查找到指定位置的元素,因此查找效率高,但每次插入或刪除元素,就要大量地移動(dòng)元素,插入刪除元素的效率低。它允許任何符合規(guī)則的元素插入甚至包括null。每一個(gè)ArrayList都有一個(gè)初始容量(10),該容量代表了數(shù)組的大小。隨著容器中的元素不斷增加,容器的大小也會(huì)隨著增加。在每次向容器中增加元素的同時(shí)都會(huì)進(jìn)行容量檢查,當(dāng)快溢出時(shí),就會(huì)進(jìn)行擴(kuò)容操作(擴(kuò)容1.5倍)。所以如果我們明確所插入元素的多少,最好指定一個(gè)初始容量值,避免過(guò)多的進(jìn)行擴(kuò)容操作而浪費(fèi)時(shí)間、效率。

ArrayList擅長(zhǎng)于隨機(jī)訪問(wèn)。同時(shí)ArrayList是非同步的,只能用在單線程環(huán)境下,多線程環(huán)境下可以考慮用Collections.synchronizedList(List l)函數(shù)返回一個(gè)線程安全的ArrayList類,也可以使用concurrent并發(fā)包下的CopyOnWriteArrayList類。

擴(kuò)充容量的方法ensureCapacity。ArrayList在每次增加元素(可能是1個(gè),也可能是一組)時(shí),都要調(diào)用該方法來(lái)確保足夠的容量。當(dāng)容量不足以容納當(dāng)前的元素個(gè)數(shù)時(shí),就設(shè)置新的容量為舊的容量的1.5倍,如果設(shè)置后的新容量還不夠,則直接新容量設(shè)置為傳入的參數(shù)(也就是所需的容量),而后用Arrays.copyof()方法將元素拷貝到新的數(shù)組。從中可以看出,當(dāng)容量不夠時(shí),每次增加元素,都要將原來(lái)的元素拷貝到一個(gè)新的數(shù)組中,非常之耗時(shí),也因此建議在事先能確定元素?cái)?shù)量的情況下,才使用ArrayList,否則建議使用LinkedList。

ArrayList的具體實(shí)現(xiàn)請(qǐng)參考這里

LinkedList

LinkedList同樣實(shí)現(xiàn)List接口,與ArrayList不同的是,LinkedList是基于雙向鏈表實(shí)現(xiàn)的,可以在任何位置進(jìn)行高效地插入和移除操作。但是LinkedList不能隨機(jī)訪問(wèn),它所有的操作都是要按照雙重鏈表的需要執(zhí)行。在列表中索引的操作將從開(kāi)頭或結(jié)尾遍歷列表(從靠近指定索引的一端)。這樣做的好處就是可以通過(guò)較低的代價(jià)在List中進(jìn)行插入和刪除操作。

與ArrayList一樣,LinkedList也是非同步的。如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)List,則必須自己實(shí)現(xiàn)訪問(wèn)同步。一種解決方法是在創(chuàng)建List時(shí)構(gòu)造一個(gè)同步的List:

List list = Collections.synchronizedList(new LinkedList(…));

LinkedList的具體實(shí)現(xiàn)請(qǐng)參考這里

Vector

與ArrayList相似,但是Vector是同步的。所以說(shuō)Vector是線程安全的動(dòng)態(tài)數(shù)組。它的操作與ArrayList幾乎一樣。

Vector的具體實(shí)現(xiàn)請(qǐng)參考這里

Stack

Stack繼承自Vector,實(shí)現(xiàn)一個(gè)后進(jìn)先出的堆棧。Stack提供5個(gè)額外的方法使得Vector得以被當(dāng)作堆棧使用。基本的push和pop 方法,還有peek方法得到棧頂?shù)脑兀琫mpty方法測(cè)試堆棧是否為空,search方法檢測(cè)一個(gè)元素在堆棧中的位置。Stack剛創(chuàng)建后是空棧。

Stack的具體實(shí)現(xiàn)請(qǐng)參考這里

Set

Set接口繼承了Collection接口。Set集合中不能包含重復(fù)的元素,每個(gè)元素必須是唯一的。你只需將元素加入set中,重復(fù)的元素會(huì)自動(dòng)移除。有三種常見(jiàn)的Set實(shí)現(xiàn)——HashSet, TreeSet和LinkedHashSet。如果你需要一個(gè)訪問(wèn)快速的Set,你應(yīng)該使用HashSet;當(dāng)你需要一個(gè)排序的Set,你應(yīng)該使用TreeSet;當(dāng)你需要記錄下插入時(shí)的順序時(shí),你應(yīng)該使用LinedHashSet。

HashSet

HashSet是是基于 HashMap 實(shí)現(xiàn)的,底層采用 HashMap 來(lái)保存元素,所以它不保證set 的迭代順序;特別是它不保證該順序恒久不變。add()、remove()以及contains()等方法都是復(fù)雜度為O(1)的方法。由于HashMap中key不可重復(fù),所以HashSet元素不可重復(fù)。可以存儲(chǔ)null元素,是線程不安全的。

TreeSet

TreeSet是一個(gè)有序集,基于TreeMap實(shí)現(xiàn),是線程不安全的。

TreeSet底層采用TreeMap存儲(chǔ),構(gòu)造器啟動(dòng)時(shí)新建TreeMap。TreeSet存儲(chǔ)元素實(shí)際為TreeMap存儲(chǔ)的鍵值對(duì)為的key;,PRESENT為固定對(duì)象:private static final Object PRESENT = new Object().

TreeSet支持兩種兩種排序方式,通過(guò)不同構(gòu)造器調(diào)用實(shí)現(xiàn)

自然排序:

public TreeSet() {
    // 新建TreeMap,自然排序
    this(new TreeMap());
}

Comparator排序:

public TreeSet(Comparator comparator) {
    // 新建TreeMap,傳入自定義比較器comparator
    this(new TreeMap<>(comparator));
}

TreeSet支持正向/反向迭代器遍歷和foreach遍歷

// 順序TreeSet:迭代器實(shí)現(xiàn)
Iterator iter = set.iterator();
while (iter.hasNext()) {
    System.out.println(iter.next());
    
}

// 順序遍歷TreeSet:foreach實(shí)現(xiàn)
for (Integer i : set) {
    System.out.println(i);
}

// 逆序遍歷TreeSet:反向迭代器實(shí)現(xiàn)
Iterator iter1 = set.descendingIterator();
while (iter1.hasNext()) {
    System.out.println(iter1.next());
}
LinkedHashSet

LinkedHashSet介于HashSet和TreeSet之間。哈希表和鏈接列表實(shí)現(xiàn)。基本方法的復(fù)雜度為O(1)。

LinkedHashSet 是 Set 的一個(gè)具體實(shí)現(xiàn),其維護(hù)著一個(gè)運(yùn)行于所有條目的雙重鏈接列表。此鏈接列表定義了迭代順序,該迭代順序可為插入順序或是訪問(wèn)順序。

LinkedHashSet 繼承于 HashSet,并且其內(nèi)部是通過(guò) LinkedHashMap 來(lái)實(shí)現(xiàn)的。有點(diǎn)類似于我們之前說(shuō)的LinkedHashMap 其內(nèi)部是基于 Hashmap 實(shí)現(xiàn)的一樣。

如果我們需要迭代的順序?yàn)椴迦腠樞蚧蛘咴L問(wèn)順序,那么 LinkedHashSet 是需要你首先考慮的。

LinkedHashSet 底層使用 LinkedHashMap 來(lái)保存所有元素,因?yàn)槔^承于 HashSet,所有的方法操作上又與 HashSet 相同,因此 LinkedHashSet 的實(shí)現(xiàn)上非常簡(jiǎn)單,只提供了四個(gè)構(gòu)造方法,并通過(guò)傳遞一個(gè)標(biāo)識(shí)參數(shù),調(diào)用父類的構(gòu)造器,底層構(gòu)造一個(gè) LinkedHashMap 來(lái)實(shí)現(xiàn),在相關(guān)操作上與父類 HashSet 的操作相同,直接調(diào)用父類 HashSet 的方法即可。

package java.util;

public class LinkedHashSet
    extends HashSet
    implements Set, Cloneable, java.io.Serializable {

    private static final long serialVersionUID = -2851667679971038690L;

    /**
     * 構(gòu)造一個(gè)帶有指定初始容量和加載因子的空鏈表哈希set。
     *
     * 底層會(huì)調(diào)用父類的構(gòu)造方法,構(gòu)造一個(gè)有指定初始容量和加載因子的LinkedHashMap實(shí)例。
     * @param initialCapacity 初始容量。
     * @param loadFactor 加載因子。
     */
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

    /** 
     * 構(gòu)造一個(gè)指定初始容量和默認(rèn)加載因子0.75的新鏈表哈希set。 
     * 
     * 底層會(huì)調(diào)用父類的構(gòu)造方法,構(gòu)造一個(gè)指定初始容量和默認(rèn)加載因子0.75的LinkedHashMap實(shí)例。 
     * @param initialCapacity 初始容量。 
     */  
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }

    /** 
     * 構(gòu)造一個(gè)默認(rèn)初始容量16和加載因子0.75的新鏈表哈希set。 
     * 
     * 底層會(huì)調(diào)用父類的構(gòu)造方法,構(gòu)造一個(gè)默認(rèn)初始容量16和加載因子0.75的LinkedHashMap實(shí)例。 
     */  
    public LinkedHashSet() {
        super(16, .75f, true);
    }

    /** 
     * 構(gòu)造一個(gè)與指定collection中的元素相同的新鏈表哈希set。 
     *  
     * 底層會(huì)調(diào)用父類的構(gòu)造方法,構(gòu)造一個(gè)足以包含指定collection 
     * 中所有元素的初始容量和加載因子為0.75的LinkedHashMap實(shí)例。 
     * @param c 其中的元素將存放在此set中的collection。 
     */  
    public LinkedHashSet(Collection c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

    
    @Override
    public Spliterator spliterator() {
        return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
    }
}

通過(guò)觀察HashMap的源碼我們可以發(fā)現(xiàn):

Hash Map的前三個(gè)構(gòu)造函數(shù),即訪問(wèn)權(quán)限為public類型的構(gòu)造函數(shù)均是以HashMap作為實(shí)現(xiàn)。而以LinkedHashMap作為實(shí)現(xiàn)的構(gòu)造函數(shù)的訪問(wèn)權(quán)限是默認(rèn)訪問(wèn)權(quán)限,即包內(nèi)訪問(wèn)權(quán)限。

即:在java編程中,通過(guò)new創(chuàng)建的HashSet對(duì)象均是以HashMap作為實(shí)現(xiàn)基礎(chǔ)。只有在jdk中java.util包內(nèi)的源代碼才可能創(chuàng)建以LinkedHashMap作為實(shí)現(xiàn)的HashSet(LinkedHashSet就是通過(guò)封裝一個(gè)以LinkedHashMap為實(shí)現(xiàn)的HashSet來(lái)實(shí)現(xiàn)的)。

只有包含三個(gè)參數(shù)的構(gòu)造函數(shù)才是采用的LinkedHashMap作為實(shí)現(xiàn)。

Map

Map與List、Set接口不同,它是由一系列鍵值對(duì)組成的集合,提供了key到Value的映射。同時(shí)它也沒(méi)有繼承Collection。在Map中它保證了key與value之間的一一對(duì)應(yīng)關(guān)系。也就是說(shuō)一個(gè)key對(duì)應(yīng)一個(gè)value,所以它不能存在相同的key值,當(dāng)然value值可以相同。key可以為空,但是只允許出現(xiàn)一個(gè)null。它的主要實(shí)現(xiàn)類有HashMap、HashTable、LinkedHashMap、TreeMap。

HashMap

HashMap 是 Map 的一個(gè)實(shí)現(xiàn)類,它代表的是一種鍵值對(duì)的數(shù)據(jù)存儲(chǔ)形式。

大多數(shù)情況下可以直接定位到它的值,因而具有很快的訪問(wèn)速度,但遍歷順序卻是不確定的。

HashMap最多只允許一條記錄的鍵為null,允許多條記錄的值為null。遇到key為null的時(shí)候,調(diào)用putForNullKey方法進(jìn)行處理,而對(duì)value沒(méi)有處理。不保證有序(比如插入的順序)、也不保證序不隨時(shí)間變化。

jdk 8 之前,其內(nèi)部是由數(shù)組+鏈表來(lái)實(shí)現(xiàn)的,而 jdk 8 對(duì)于鏈表長(zhǎng)度超過(guò) 8 的鏈表將轉(zhuǎn)儲(chǔ)為紅黑樹(shù)。

HashMap非線程安全,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫(xiě)HashMap,可能會(huì)導(dǎo)致數(shù)據(jù)的不一致。如果需要滿足線程安全,可以用 Collections的synchronizedMap方法使HashMap具有線程安全的能力,或者使用ConcurrentHashMap。

hash數(shù)組的默認(rèn)大小是16,而且大小一定是2的指數(shù)

HashMap的具體實(shí)現(xiàn)請(qǐng)參考這里

HashTable

Hashtable和HashMap一樣也是散列表,存儲(chǔ)元素也是鍵值對(duì),底層實(shí)現(xiàn)是一個(gè)Entry數(shù)組+鏈表。Hashtable繼承于Dictionary類(Dictionary類聲明了操作鍵值對(duì)的接口方法),實(shí)現(xiàn)Map接口(定義鍵值對(duì)接口)。HashTable是線程安全的,它的大部分類都被synchronized關(guān)鍵字修飾。key和value都不可為null。

hash數(shù)組默認(rèn)大小是11,擴(kuò)充方式是old*2+1

LinkedHashMap

LinkedHashMap繼承自HashMap實(shí)現(xiàn)了Map接口。基本實(shí)現(xiàn)同HashMap一樣(底層基于數(shù)組+鏈表+紅黑樹(shù)實(shí)現(xiàn)),不同之處在于LinkedHashMap保證了迭代的有序性。其內(nèi)部維護(hù)了一個(gè)雙向鏈表,解決了 HashMap不能隨時(shí)保持遍歷順序和插入順序一致的問(wèn)題。
除此之外,LinkedHashMap對(duì)訪問(wèn)順序也提供了相關(guān)支持。在一些場(chǎng)景下,該特性很有用,比如緩存。

在實(shí)現(xiàn)上,LinkedHashMap很多方法直接繼承自HashMap,僅為維護(hù)雙向鏈表覆寫(xiě)了部分方法。

默認(rèn)情況下,LinkedHashMap的迭代順序是按照插入節(jié)點(diǎn)的順序。也可以通過(guò)改變accessOrder參數(shù)的值,使得其遍歷順序按照訪問(wèn)順序輸出。

LinkedHashMap的具體實(shí)現(xiàn)請(qǐng)參考這里

TreeMap

TreeMap繼承自AbstractMap抽象類,并實(shí)現(xiàn)了SortedMap接口,如下圖所示:

[圖片上傳失敗...(image-fd7a40-1530872801038)]

TreeMap集合是基于紅黑樹(shù)(Red-Black tree)的 NavigableMap實(shí)現(xiàn)。該集合最重要的特點(diǎn)就是可排序,該映射根據(jù)其鍵的自然順序進(jìn)行排序,或者根據(jù)創(chuàng)建映射時(shí)提供的 Comparator 進(jìn)行排序,具體取決于使用的構(gòu)造方法。

關(guān)于集合的常見(jiàn)問(wèn)題 List和Map的區(qū)別

都是Java常用的容器,都是接口。不同的是List存儲(chǔ)的是單列的集合,Map存儲(chǔ)的是key-value鍵值對(duì)的集合。List中允許出現(xiàn)重復(fù)元素,Map中不允許key重復(fù)。List集合是有序的(儲(chǔ)存有序),Map集合是無(wú)序的(存儲(chǔ)無(wú)序)

Set中的元素不能重復(fù),如何實(shí)現(xiàn)?

Set大多都用的Map接口的實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)的(HashSet基于HashMap實(shí)現(xiàn),TreeSet基于TreeMap實(shí)現(xiàn),LinkedHashSet基于LinkedHashMap實(shí)現(xiàn))
在HashMap中通過(guò)如下實(shí)現(xiàn)來(lái)保證key值唯一

 // 1. 如果key 相等  
if (p.hash == hash &&
    ((k = p.key) == key || (key != null && key.equals(k))))
    e = p;
// 2. 修改對(duì)應(yīng)的value
   if (e != null) { // existing mapping for key
        V oldValue = e.value;
        if (!onlyIfAbsent || oldValue == null)
            e.value = value;
        afterNodeAccess(e);
        return oldValue;
   }

添加元素的時(shí)候,如果key(也對(duì)應(yīng)的Set集合的元素)相等,那么則修改value值。而在Set集合中,value值僅僅是一個(gè)Object對(duì)象罷了(該對(duì)象對(duì)Set本身而言是無(wú)用的)。

也就是說(shuō):Set集合如果添加的元素相同時(shí),是根本沒(méi)有插入的(僅修改了一個(gè)無(wú)用的value值)。從源碼(HashMap)中也看出來(lái),==和equals()方法都有使用!

Vector和ArrayList

相同點(diǎn):
這兩個(gè)類都實(shí)現(xiàn)了List接口,他們都是有序的集合(儲(chǔ)存有序),底層都用數(shù)組實(shí)現(xiàn)。可以通過(guò)索引來(lái)獲取某個(gè)元素。允許元素重復(fù)和出現(xiàn)null值。ArrayList和Vector的迭代器實(shí)現(xiàn)都是fail-fast的。

不同點(diǎn):
vector是線程同步的,所以它也是線程安全的,而arraylist是線程異步的,是不安全的。如果不考慮到線程的安全因素,一般用arraylist效率比較高。

擴(kuò)容時(shí),arraylist擴(kuò)容1.5倍,vector擴(kuò)容2倍(或者擴(kuò)容指定的大小)

ArrayList 和Vector是采用數(shù)組方式存儲(chǔ)數(shù)據(jù),此數(shù)組元素?cái)?shù)大于實(shí)際存儲(chǔ)的數(shù)據(jù)以便增加和插入元素,都允許直接序號(hào)索引元素,但是插入數(shù)據(jù)要設(shè)計(jì)到數(shù)組元素移動(dòng)等內(nèi)存操作,所以索引數(shù)據(jù)快插入數(shù)據(jù)慢,Vector由于使用了synchronized方法(線程安全)所以性能上比ArrayList要差,LinkedList使用雙向鏈表實(shí)現(xiàn)存儲(chǔ),按序號(hào)索引數(shù)據(jù)需要進(jìn)行向前或向后遍歷,但是插入數(shù)據(jù)時(shí)只需要記錄本項(xiàng)的前后項(xiàng)即可,所以插入數(shù)度較快!

Aarraylist和Linkedlist

ArrayList是基于數(shù)組實(shí)現(xiàn)的,LinkedList基于雙向鏈表實(shí)現(xiàn)的。

ArrayList它支持以下標(biāo)位置進(jìn)行索引出對(duì)應(yīng)的元素(隨機(jī)訪問(wèn)),而LinkedList則需要遍歷整個(gè)鏈表來(lái)獲取對(duì)應(yīng)的元素。因此一般來(lái)說(shuō)ArrayList的訪問(wèn)速度是要比LinkedList要快的

ArrayList由于是數(shù)組,對(duì)于刪除和修改而言消耗是比較大(復(fù)制和移動(dòng)數(shù)組實(shí)現(xiàn)),LinkedList是雙向鏈表刪除和修改只需要修改對(duì)應(yīng)的指針即可,消耗是很小的。因此一般來(lái)說(shuō)LinkedList的增刪速度是要比ArrayList要快的

LinkedList比ArrayList消耗更多的內(nèi)存,因?yàn)長(zhǎng)inkedList中的每個(gè)節(jié)點(diǎn)存儲(chǔ)了前后節(jié)點(diǎn)的引用。

對(duì)于增加/刪除元素操作

如果增刪都是在末尾來(lái)操作(每次調(diào)用的都是remove()和add()),此時(shí)ArrayList就不需要移動(dòng)和復(fù)制數(shù)組來(lái)進(jìn)行操作了。如果數(shù)據(jù)量有百萬(wàn)級(jí)的時(shí),速度是會(huì)比LinkedList要快的。

如果刪除操作的位置是在中間。由于LinkedList的消耗主要是在遍歷上,ArrayList的消耗主要是在移動(dòng)和復(fù)制上(底層調(diào)用的是arraycopy()方法,是native方法)。
LinkedList的遍歷速度是要慢于ArrayList的復(fù)制移動(dòng)速度的
如果數(shù)據(jù)量有百萬(wàn)級(jí)的時(shí),還是ArrayList要快。

哪些集合類提供對(duì)元素的隨機(jī)訪問(wèn)?

ArrayList、HashMap、TreeMap和HashTable類提供對(duì)元素的隨機(jī)訪問(wèn)。

Enumeration和Iterator接口的區(qū)別

Enumeration的速度是Iterator的兩倍,也使用更少的內(nèi)存。Enumeration是非常基礎(chǔ)的,也滿足了基礎(chǔ)的需要。但是,與Enumeration相比,Iterator更加安全,因?yàn)楫?dāng)一個(gè)集合正在被遍歷的時(shí)候,它會(huì)阻止其它線程去修改集合。

Iterator的方法名比Enumeration更科學(xué)
Iterator有fail-fast機(jī)制,比Enumeration更安全
Iterator能夠刪除元素,Enumeration并不能刪除元素

Iterater和ListIterator之間有什么區(qū)別?

我們可以使用Iterator來(lái)遍歷Set和List集合,而ListIterator只能遍歷List。
Iterator只可以向前遍歷,而LIstIterator可以雙向遍歷。
ListIterator從Iterator接口繼承,然后添加了一些額外的功能,比如添加一個(gè)元素、替換一個(gè)元素、獲取前面或后面元素的索引位置。

Java中HashMap的key值要是為類對(duì)象則該類需要滿足什么條件?

需要同時(shí)重寫(xiě)該類的hashCode()方法和它的equals()方法。

從源碼可以得知,在插入元素的時(shí)候是先算出該對(duì)象的hashCode。如果hashcode相等話的。那么表明該對(duì)象是存儲(chǔ)在同一個(gè)位置上的。
如果調(diào)用equals()方法,兩個(gè)key相同,則替換元素
如果調(diào)用equals()方法,兩個(gè)key不相同,則說(shuō)明該hashCode僅僅是碰巧相同,此時(shí)是散列沖突,將新增的元素放在桶子上

重寫(xiě)了equals()方法,就要重寫(xiě)hashCode()的方法。因?yàn)閑quals()認(rèn)定了這兩個(gè)對(duì)象相同,而同一個(gè)對(duì)象調(diào)用hashCode()方法時(shí),是應(yīng)該返回相同的值的!

HashSet與HashMap

HashSet 實(shí)現(xiàn)了 Set 接口,它不允許集合中有重復(fù)的值,當(dāng)我們提到 HashSet 時(shí),第一件事情就是在將對(duì)象存儲(chǔ)在 HashSet 之前,要先確保對(duì)象重寫(xiě) equals()和 hashCode()方法,這樣才能比較對(duì)象的值是否相等,以確保set中沒(méi)有儲(chǔ)存相等的對(duì)象。如果我們沒(méi)有重寫(xiě)這兩個(gè)方法,將會(huì)使用這個(gè)方法的默認(rèn)實(shí)現(xiàn)。

public boolean add(Object o)方法用來(lái)在 Set 中添加元素,當(dāng)元素值重復(fù)時(shí)則會(huì)立即返回 false,如果成功添加的話會(huì)返回 true。

HashMap 實(shí)現(xiàn)了 Map 接口,Map 接口對(duì)鍵值對(duì)進(jìn)行映射。Map 中不允許重復(fù)的鍵。Map 接口有兩個(gè)基本的實(shí)現(xiàn),HashMap 和 TreeMap。TreeMap 保存了對(duì)象的排列次序,而 HashMap 則不能。HashMap 允許鍵和值為 null。HashMap 是非 synchronized 的,但 collection 框架提供方法能保證 HashMap synchronized,這樣多個(gè)線程同時(shí)訪問(wèn) HashMap 時(shí),能保證只有一個(gè)線程更改 Map。

public Object put(Object Key,Object value)方法用來(lái)將元素添加到 map 中。

HashMap HashSet
HashMap實(shí)現(xiàn)了Map接口 HashSet實(shí)現(xiàn)了Set接口
HashMap儲(chǔ)存鍵值對(duì) HashSet僅僅存儲(chǔ)對(duì)象
使用put()方法將元素放入map中 使用add()方法將元素放入set中
HashMap中使用鍵對(duì)象來(lái)計(jì)算hashcode值 HashSet使用成員對(duì)象來(lái)計(jì)算hashcode值,對(duì)于兩個(gè)對(duì)象來(lái)說(shuō)hashcode可能相同,所以equals()方法用來(lái)判斷對(duì)象的相等性,如果兩個(gè)對(duì)象不同的話,那么返回false
hashtable與hashmap

相同點(diǎn):
儲(chǔ)存結(jié)構(gòu)和實(shí)現(xiàn)基本相同,都是是實(shí)現(xiàn)的Map接口

不同點(diǎn):
HashTable是同步的,HashMap是非同步的,需要同步的時(shí)候可以ConcurrentHashMap方法

HashMap允許為null,HashTable不允許為null

繼承不同,HashMap繼承的是AbstractMap,HashTable繼承的是Dictionary

HashMap提供對(duì)key的Set進(jìn)行遍歷,因此它是fail-fast的,但HashTable提供對(duì)key的Enumeration進(jìn)行遍歷,它不支持fail-fast。

HashTable是一個(gè)遺留類,如果需要保證線程安全推薦使用CocurrentHashMap

HashMap與TreeMap

HashMap通過(guò)hashcode對(duì)其內(nèi)容進(jìn)行快速查找,而TreeMap中所有的元素都保持著某種固定的順序,如果你需要得到一個(gè)有序的結(jié)果你就應(yīng)該使用TreeMap(HashMap中元素的排列順序是不固定的)。HashMap中元素的排列順序是不固定的)。

在Map 中插入、刪除和定位元素,HashMap 是最好的選擇。但如果您要按自然順序或自定義順序遍歷鍵,那么TreeMap會(huì)更好。使用HashMap要求添加的鍵類明確定義了hashCode()和 equals()的實(shí)現(xiàn)。 這個(gè)TreeMap沒(méi)有調(diào)優(yōu)選項(xiàng),因?yàn)樵摌?shù)總處于平衡狀態(tài)。

集合框架中的泛型有什么優(yōu)點(diǎn)?

Java1.5引入了泛型,所有的集合接口和實(shí)現(xiàn)都大量地使用它。泛型允許我們?yōu)榧咸峁┮粋€(gè)可以容納的對(duì)象類型,因此,如果你添加其它類型的任何元素,它會(huì)在編譯時(shí)報(bào)錯(cuò)。這避免了在運(yùn)行時(shí)出現(xiàn)ClassCastException,因?yàn)槟銓?huì)在編譯時(shí)得到報(bào)錯(cuò)信息。泛型也使得代碼整潔,我們不需要使用顯式轉(zhuǎn)換和instanceOf操作符。它也給運(yùn)行時(shí)帶來(lái)好處,因?yàn)椴粫?huì)產(chǎn)生類型檢查的字節(jié)碼指令。

comparable 和 comparator的不同之處?

comparable接口實(shí)際上是出自java.lang包
它有一個(gè) compareTo(Object obj)方法來(lái)將objects排序
comparator接口實(shí)際上是出自 java.util 包
它有一個(gè)compare(Object obj1, Object obj2)方法來(lái)將objects排序

如何保證一個(gè)集合線程安全?

Vector, Hashtable, Properties 和 Stack 都是同步的類,所以它們都線程安全的,可以被使用在多線程環(huán)境中
使用Collections.synchronizedList(list)) 方法,可以保證list類是線程安全的
使用java.util.Collections.synchronizedSet()方法可以保證set類是線程安全的。

TreeMap和TreeSet在排序時(shí)如何比較元素?Collections工具類中的sort()方法如何比較元素?

TreeSet要求存放的對(duì)象所屬的類必須實(shí)現(xiàn)Comparable接口,該接口提供了比較元素的compareTo()方法,當(dāng)插入元素時(shí)會(huì)回調(diào)該方法比較元素的大小。

TreeMap要求存放的鍵值對(duì)映射的鍵必須實(shí)現(xiàn)Comparable接口從而根據(jù)鍵對(duì)元素進(jìn)行排序。

Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對(duì)象比較實(shí)現(xiàn)Comparable接口以實(shí)現(xiàn)元素的比較;第二種不強(qiáng)制性的要求容器中的元素必須可比較,但是要求傳入第二個(gè)參數(shù),參數(shù)是Comparator接口的子類型(需要重寫(xiě)compare方法實(shí)現(xiàn)元素的比較),相當(dāng)于一個(gè)臨時(shí)定義的排序規(guī)則,其實(shí)就是通過(guò)接口注入比較元素大小的算法,也是對(duì)回調(diào)模式的應(yīng)用(Java中對(duì)函數(shù)式編程的支持)。

什么是Java優(yōu)先級(jí)隊(duì)列?

Java PriorityQueue是一個(gè)數(shù)據(jù)結(jié)構(gòu),它是Java集合框架的一部分。 它是一個(gè)隊(duì)列的實(shí)現(xiàn),其中元素的順序?qū)⒏鶕?jù)每個(gè)元素的優(yōu)先級(jí)來(lái)決定。 實(shí)例化PriorityQueue時(shí),可以在構(gòu)造函數(shù)中提供比較器。 該比較器將決定PriorityQueue集合實(shí)例中元素的排序順序。

Java hashCode()和equals()方法。

equals()方法用于確定兩個(gè)Java對(duì)象的相等性。 當(dāng)我們有一個(gè)自定義類時(shí),我們需要重寫(xiě)equals()方法并提供一個(gè)實(shí)現(xiàn),以便它可以用來(lái)找到它的兩個(gè)實(shí)例之間的相等性。 通過(guò)Java規(guī)范,equals()和hashCode()之間有一個(gè)契約。 它說(shuō),“如果兩個(gè)對(duì)象相等,即obj1.equals(obj2)為true,那么obj1.hashCode()和obj2.hashCode()必須返回相同的整數(shù)”

無(wú)論何時(shí)我們選擇重寫(xiě)equals(),我們都必須重寫(xiě)hashCode()方法。 hashCode()用于計(jì)算位置存儲(chǔ)區(qū)和key。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71493.html

相關(guān)文章

  • Java開(kāi)發(fā)常見(jiàn)問(wèn)題集錦

    摘要:下面是一些常見(jiàn)的理解性問(wèn)題,每一個(gè)問(wèn)題盡量用圖或代碼去描述。內(nèi)容全部來(lái)自,包括基本語(yǔ)法數(shù)組集合類泛型面向?qū)ο罄厥债惓?刂戚斎胼敵龊蛢?nèi)存。不斷更新,歡迎大家提出有趣味的問(wèn)題和意見(jiàn)。 程序員經(jīng)常可以通過(guò)搜索或者記憶來(lái)完成代碼,但是許多時(shí)候并不真正理解為什么那樣寫(xiě)。也就是說(shuō),有一定經(jīng)驗(yàn)的程序員不會(huì)犯一些低級(jí)的語(yǔ)法錯(cuò)誤,但是因?yàn)椴簧钊肜斫庥锌赡茉斐梢恍└呒?jí)錯(cuò)誤,比如說(shuō)運(yùn)行無(wú)效率,代碼難De...

    MSchumi 評(píng)論0 收藏0
  • 一份送給Java初學(xué)者的指南

    摘要:編程思想第版這本書(shū)要常讀,初學(xué)者可以快速概覽,中等程序員可以深入看看,老鳥(niǎo)還可以用之回顧的體系。以下視頻整理自慕課網(wǎng)工程師路徑相關(guān)免費(fèi)課程。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問(wèn)題,目前已經(jīng)開(kāi)源,會(huì)一直完善下去,歡迎建議和指導(dǎo)歡迎Star: https://github.com/Snailclimb/Java-Guide 筆者建議初學(xué)者學(xué)習(xí)Java的方式:看書(shū)+視頻+實(shí)踐(初...

    banana_pi 評(píng)論0 收藏0
  • 04.Android之動(dòng)畫(huà)問(wèn)題

    摘要:動(dòng)畫(huà)占用大量?jī)?nèi)存,如何優(yōu)化使用動(dòng)畫(huà)的注意事項(xiàng)有哪些問(wèn)題這個(gè)問(wèn)題主要出現(xiàn)在幀動(dòng)畫(huà)中,當(dāng)圖片數(shù)量較多且圖片較大時(shí)就極易出現(xiàn),這個(gè)在實(shí)際開(kāi)發(fā)中要尤其注意,盡量避免使用幀動(dòng)畫(huà)。 目錄介紹 4.0.0.1 Android中有哪幾種類型的動(dòng)畫(huà),屬性動(dòng)畫(huà)和補(bǔ)間動(dòng)畫(huà)有何區(qū)別?補(bǔ)間動(dòng)畫(huà)和屬性動(dòng)畫(huà)常用的有哪些? 4.0.0.2 View動(dòng)畫(huà)為何不能真正改變View的位置?而屬性動(dòng)畫(huà)為何可以?屬性動(dòng)畫(huà)是如...

    Muninn 評(píng)論0 收藏0
  • Java 總結(jié)

    摘要:中的詳解必修個(gè)多線程問(wèn)題總結(jié)個(gè)多線程問(wèn)題總結(jié)有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升有哪些源代碼看了后讓你收獲很多,代碼思維和能力有較大的提升開(kāi)源的運(yùn)行原理從虛擬機(jī)工作流程看運(yùn)行原理。 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 自己實(shí)現(xiàn)集合框架 (三): 單鏈表的實(shí)現(xiàn) 基于 POI 封裝 ExcelUtil 精簡(jiǎn)的 Excel 導(dǎo)入導(dǎo)出 由于 poi 本身只是針對(duì)于 ...

    caspar 評(píng)論0 收藏0
  • Java問(wèn)題匯總,持續(xù)更新到GitHub

    摘要:目錄介紹問(wèn)題匯總具體問(wèn)題好消息博客筆記大匯總年月到至今,包括基礎(chǔ)及深入知識(shí)點(diǎn),技術(shù)博客,學(xué)習(xí)筆記等等,還包括平時(shí)開(kāi)發(fā)中遇到的匯總,當(dāng)然也在工作之余收集了大量的面試題,長(zhǎng)期更新維護(hù)并且修正,持續(xù)完善開(kāi)源的文件是格式的同時(shí)也開(kāi)源了生活博客,從年 目錄介紹 00.Java問(wèn)題匯總 01.具體問(wèn)題 好消息 博客筆記大匯總【16年3月到至今】,包括Java基礎(chǔ)及深入知識(shí)點(diǎn),Android技...

    beita 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<