Java常用集合類總結(jié)

List接口與其實(shí)現(xiàn)類

List類似于數(shù)組刹勃,可以通過索引來訪問元素,實(shí)現(xiàn)該接口的常用類有ArrayList埃碱、LinkedList猖辫、VectorStack等砚殿。

ArrayList

ArrayList是動態(tài)數(shù)組啃憎,可以根據(jù)插入的元素的數(shù)量自動擴(kuò)容,而使用者不需要知道其內(nèi)部是什么時候進(jìn)行擴(kuò)展的似炎,把它當(dāng)作足夠容量的數(shù)組來使用即可辛萍。
ArrayList訪問元素的方法get是常數(shù)時間,因?yàn)槭侵苯痈鶕?jù)下標(biāo)索引來訪問的羡藐,而add方法的時間復(fù)雜度是O(n)贩毕,因?yàn)樾枰苿釉兀瑢⑿略夭迦氲胶线m的位置传睹。
ArrayList是非線程安全的耳幢,即它沒有同步,不過欧啤,可以通過Collections.synchronizedList()靜態(tài)方法返回一個同步的實(shí)例睛藻,如:

List synList = Collections.synchronizedList(list);

數(shù)組擴(kuò)容:ArrayList在插入元素的時候,都會檢查當(dāng)前的數(shù)組大小是否足夠邢隧,如果不夠店印,將會擴(kuò)容到當(dāng)前容量 * 1.5 + 1(加1是為了當(dāng)前容量為1時,也能擴(kuò)展到2)倒慧,即把原來的元素全部復(fù)制到一個兩倍大小的新數(shù)組按摘,將舊的數(shù)組拋棄掉(等待垃圾回收),這個操作是比較耗時纫谅,因此建議在創(chuàng)建ArrayList的時候炫贤,根據(jù)要插入的元素的數(shù)量來初步估計Capacity,并初始化ArrayList付秕,如:

ArrayList list = new ArrayList(100);

這樣兰珍,在插入小于100個元素的時候都是不需要進(jìn)行擴(kuò)容的,能夠帶來性能的提升询吴,當(dāng)然掠河,如果對這個容量估計大了,可能會帶來一些空間的損耗猛计。

LinkedList

LinkedList也實(shí)現(xiàn)了List接口唠摹,其內(nèi)部實(shí)現(xiàn)是使用雙向鏈表來保存元素,因此插入與刪除元素的性能都表現(xiàn)不錯奉瘤。它還提供了一些其它操作方法勾拉,如在頭部、尾部插入或者刪除元素,因此望艺,可以用它來實(shí)現(xiàn)棧苛秕、隊列、雙向隊列找默。
由于是使用鏈表保存元素的,所以隨機(jī)訪問元素的時候速度會比較慢(需要遍歷鏈表找到目標(biāo)元素)吼驶,這一點(diǎn)相比ArrayList的隨機(jī)訪問要差惩激,ArrayList是采用數(shù)組實(shí)現(xiàn)方式,直接使用下標(biāo)可以訪問到元素而不需要遍歷蟹演。因此风钻,在需要頻繁隨機(jī)訪問元素的情況下,建議使用ArrayList酒请。
與ArrayList一樣骡技,LinkedList也是非同步的,如果需要實(shí)現(xiàn)多線程訪問羞反,則需要自己在外部實(shí)現(xiàn)同步方法布朦。當(dāng)然也可以使用Collections.synchronizedList()靜態(tài)方法。

Vector

Vector是ArrayList的線程同步版本昼窗,即是說Vector是同步的是趴,支持多線程訪問。除此之外澄惊,還有一點(diǎn)不同時唆途,當(dāng)容量不夠時,Vector默認(rèn)擴(kuò)展一倍容量掸驱,而ArrayList是當(dāng)前容量 * 1.5 + 1

Stack

Stack是一種后進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)肛搬,繼承自Vector類,提供了push毕贼、pop温赔、peek(獲得棧頂元素)等方法。

Set接口

Set是不能包含重合元素的容器帅刀,其實(shí)現(xiàn)類有HashSet让腹,繼承于它的接口有SortedSet接口等。Set中提供了加扣溺、減骇窍、和交等集合操作函數(shù)。Set不能按照索引隨機(jī)訪問元素锥余,這是它與List的一個重要區(qū)別腹纳。

HashSet

HashSet實(shí)現(xiàn)了Set接口,其內(nèi)部是采用HashMap實(shí)現(xiàn)的。放入HashSet的對象最好重寫hashCode嘲恍、equals方法足画,因?yàn)槟J(rèn)的這兩個方法很可能與你的業(yè)務(wù)邏輯是不一致的,而且佃牛,要同時重寫這兩個函數(shù)淹辞,如果只重寫其中一個,很容易發(fā)生意想不到的問題俘侠。
記住下面幾條規(guī)則:

  • 相等對象象缀,hashCode一定相等。
  • 不等對象爷速,hashCode不一定不相等央星。
  • 兩個對象的hashCode相同,不一定相等惫东。
  • 兩個對象的hashCode不同莉给,一定不相等。

TreeSet

TreeSet同樣的Set接口的實(shí)現(xiàn)類廉沮,同樣不能存放相同的對象颓遏。它與HashSet不同的是,TreeSet的元素是按照順序排列的废封,因此用TreeSet存放的對象需要實(shí)現(xiàn)Comparable接口州泊。

Map接口

Map集合提供了按照“鍵值對”存儲元素的方法,一個鍵唯一映射一個值漂洋。集合中“鍵值對”整體作為一個實(shí)體元素時遥皂,類似List集合,但是如果分開來年刽漂,Map是一個兩列元素的集合:鍵是一列演训,值是一列。與Set集合一樣贝咙,Map也沒有提供隨機(jī)訪問的能力样悟,只能通過鍵來訪問對應(yīng)的值。
Map的每一個元素都是一個Map.Entry庭猩,這個實(shí)體的結(jié)構(gòu)是< Key, Value >樣式窟她。

HashMap

HashMap實(shí)現(xiàn)了Map接口,但它是非線程安全的蔼水。HashMap允許key值為null震糖,value也可以為null

Hashtable

Hashtable也是Map的實(shí)現(xiàn)類趴腋,繼承自Dictionary類吊说。它與HashMap不同的是论咏,它是線程安全的。而且它不允許keynull颁井,value也不能為null厅贪。
由于它是線程安全的,在效率上稍差于HashMap雅宾。

List總結(jié)

ArrayList內(nèi)部實(shí)現(xiàn)采用動態(tài)數(shù)組养涮,當(dāng)容量不夠時,自動擴(kuò)容至(當(dāng)前容量1.5+1)秀又。元素的順序按照插入的順序排列单寂。默認(rèn)初始容量為10。
contains復(fù)雜度為O(n)吐辙,add復(fù)雜度為分?jǐn)偟某?shù),即添加n個元素需要O(n)時間蘸劈,remove為O(n)昏苏,get復(fù)雜度為O(1)
隨機(jī)訪問效率高,隨機(jī)插入威沫、刪除效率低贤惯。ArrayList是
非線程安全*的。

LinkedList內(nèi)部使用雙向鏈表實(shí)現(xiàn)棒掠,隨機(jī)訪問效率低孵构,隨機(jī)插入、刪除效率高烟很【笔可以當(dāng)作堆棧、隊列雾袱、雙向隊列來使用恤筛。LinkedList也是非線程安全的。

Vector跟ArrayList是類似的芹橡,內(nèi)部實(shí)現(xiàn)也是動態(tài)數(shù)組毒坛,隨機(jī)訪問效率高。Vector是線程安全的林说。

Stack是棧煎殷,繼承于Vector,其各種操作也是基于Vector的各種操作腿箩,因此其內(nèi)部實(shí)現(xiàn)也是動態(tài)數(shù)組豪直,先進(jìn)后出。Stack是線程安全的度秘。

List使用場景

  • 對于需要快速插入顶伞、刪除元素饵撑,應(yīng)該使用LinkedList
  • 對于需要快速隨機(jī)訪問元素,應(yīng)該使用ArrayList
  • 如果List需要被多線程操作唆貌,應(yīng)該使用Vector滑潘,如果只會被單線程操作,應(yīng)該使用ArrayList

Set總結(jié)

HashSet內(nèi)部是使用HashMap實(shí)現(xiàn)的锨咙,HashSet的key值是不允許重復(fù)的语卤,如果放入的對象是自定義對象,那么最好能夠同時重寫hashCodeequals函數(shù)酪刀,這樣就能自定義添加的對象在什么樣的情況下是一樣的粹舵,即能保證在業(yè)務(wù)邏輯下能添加對象到HashSet中,保證業(yè)務(wù)邏輯的正確性骂倘。另外眼滤,HashSet里的元素不是按照順序存儲的。HashSet是非線程安全的历涝。

TreeSet存儲的元素是按順序存儲的诅需,如果是存儲的元素是自定義對象,那么需要實(shí)現(xiàn)Comparable接口荧库。TreeSet也是非線程安全的堰塌。

LinkedHashSet繼承自HashSet,它與HashSet不同的是分衫,LinkedHashSet存儲元素的順序是按照元素的插入順序存儲的场刑。LinkedHashSet也是非線程安全的。

Map總結(jié)

HashMap存儲鍵值對蚪战。當(dāng)程序試圖將一個key-value對放入 HashMap 中時牵现,程序首先根據(jù)該keyhashCode()返回值決定該Entry的存儲位置:如果兩個EntrykeyhashCode() 返回值相同,那它們的存儲位置相同屎勘。如果這兩個Entrykey通過equals比較返回true施籍,新添加Entryvalue將覆蓋集合中原有Entryvalue,但key不會覆蓋概漱。如果這兩個Entrykey通過equals 比較返回false丑慎,新添加的Entry將與集合中原有Entry形成Entry 鏈,而且新添加的 Entry 位于 Entry 鏈的頭部瓤摧「土眩看下面HashMap添加鍵值對的源代碼:

public V put(K key, V value) {
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key.hashCode());
    int i = indexFor(hash, table.length);
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K,V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<>(hash, key, value, e);
    if (size++ >= threshold)
        resize(2 * table.length);
}

HashMap允許keyvalue值為null照弥。HashMap是非線程安全的腻异。

Hashtable是HashMap的線程安全版本。而且悔常,key影斑、value都不允許為null机打。

哈希值的使用不同: Hashtable直接使用對象的hashCode,如下代碼:

int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;

而HashMap重新計算hash值残邀,如下代碼:

int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);

static int hash(int h) {
    // This function ensures that hashCodes that differ only by
    // constant multiples at each bit position have a bounded
    // number of collisions (approximately 8 at default load factor).
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
    return h & (length-1);
}

擴(kuò)展容量不同: Hashtable中hash數(shù)組默認(rèn)大小是11,增加的方式是 old*2+1芥挣。HashMap中hash數(shù)組的默認(rèn)大小是16驱闷,而且一定是2的指數(shù)空免。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末空另,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蹋砚,更是在濱河造成了極大的恐慌痹换,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件都弹,死亡現(xiàn)場離奇詭異,居然都是意外死亡匙姜,警方通過查閱死者的電腦和手機(jī)畅厢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氮昧,“玉大人框杜,你說我怎么就攤上這事⌒浞剩” “怎么了咪辱?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長椎组。 經(jīng)常有香客問我油狂,道長,這世上最難降的妖魔是什么寸癌? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任专筷,我火速辦了婚禮,結(jié)果婚禮上蒸苇,老公的妹妹穿的比我還像新娘磷蛹。我一直安慰自己,他們只是感情好溪烤,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布味咳。 她就那樣靜靜地躺著庇勃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪槽驶。 梳的紋絲不亂的頭發(fā)上责嚷,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音捺檬,去河邊找鬼再层。 笑死,一個胖子當(dāng)著我的面吹牛堡纬,可吹牛的內(nèi)容都是我干的聂受。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼烤镐,長吁一口氣:“原來是場噩夢啊……” “哼蛋济!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起炮叶,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤碗旅,失蹤者是張志新(化名)和其女友劉穎镜悉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體旧困,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡稼锅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拗盒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锥债。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖毅整,靈堂內(nèi)的尸體忽然破棺而出绽左,到底是詐尸還是另有隱情,我是刑警寧澤拼窥,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布蹋凝,位于F島的核電站鳍寂,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏迄汛。R本人自食惡果不足惜骤视,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望睹逃。 院中可真熱鬧,春花似錦沉填、人聲如沸佑笋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春史汗,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背停撞。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留艰猬,地道東北人埋市。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像食听,于是被迫代替她去往敵國和親胸蛛。 傳聞我的和親對象是個殘疾皇子葬项,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Collection & Map Collection 子類有 List 和 Set List --> Array...
    任教主來也閱讀 3,145評論 1 9
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法民珍,類相關(guān)的語法盗飒,內(nèi)部類的語法,繼承相關(guān)的語法箩兽,異常的語法,線程的語...
    子非魚_t_閱讀 31,587評論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個變量的值是否相等身坐,對于引用型變量表示的是兩個變量...
    jmychou閱讀 1,485評論 0 3
  • 一咐蝇、基本數(shù)據(jù)類型 注釋 單行注釋:// 區(qū)域注釋:/* */ 文檔注釋:/** */ 數(shù)值 對于byte類型而言...
    龍貓小爺閱讀 4,254評論 0 16
  • 夜間,看到旁邊的吉他抹腿,已經(jīng)擱置很久了。幾年前圖新鮮警绩,想耍帥,其實(shí)一個更隱秘的理由肩祥,沒有人知道,我只是想幫他繼續(xù)實(shí)現(xiàn)...
    珂珂成長ing閱讀 263評論 2 2