集合學習筆記

2021-10-08 11:17:46 字數 4498 閱讀 8866

此文為讀書摘抄筆記,摘抄自這裡

list、set是,map不是。map是鍵值對對映容器,與list和set有明顯的區別,而set儲存的零散的元素且不允許有重複元素,list是線性結構的容器,適用於按數值索引訪問元素的情形。

arraylist和linkedlist都實現了list介面,他們有以下的不同點:

是否保證執行緒安全:arraylist和linkedlist都是不同步的,也就是不保證執行緒安全。

底層資料結構:arraylist底層使用的是object陣列,linkedlist底層使用的是雙向鍊錶資料結構。

插入和刪除是否受元素位置的影響:①arraylist採用陣列儲存,所以插入和刪除元素的時間複雜度受元素位置的影響。當執行add(e e)方法時,arraylist會預設在將指定的元素追加到此列表的末尾,此時時間複雜度為o(1)。當要在指定位置i插入和刪除元素的話,執行add(int index,e element),此時時間複雜度九尾o(n-i)。因為在進行上述操作的時候集合中第i和第i個元素之後的(n-i)個元素都要執行向後/向前移一位的操作。②linkedlist採用鍊錶儲存,當執行add(e e)方法時,插入刪除元素的時間複雜度不受元素位置影響,近似o(1),如果是要在指定位置i插入和刪除元素的話,時間複雜度則近似為o(n),因為需要先移動到指定位置在插入。

新增插入刪除的速度:相對於arraylist,linkedlist的插入、新增和刪除操作速度更快,因為當元素被新增到集合任意位置的時候,不需要像陣列那樣重新計算大小或者是更新索引。

是否支援快速隨機訪問:①arraylist是基於索引的資料介面,底層是陣列,它可以以o(1)時間複雜度對元素進行隨機訪問,快速隨機訪問就是通過元素的序號快速獲取元素物件(對應於get(int index)方法)。②linkedlist不支援高效的隨機元素訪問,它每乙個元素和它的前乙個和後乙個元素連線在一起,在這種情況下,查詢某個元素的時間複雜度是o(n)。

記憶體空間占用:arraylist的空間浪費主要體現在list列表的結尾會預留一定的容量空間,而linkedlist比arraylist更佔記憶體,因為linkedlist為每乙個節點儲存了兩個引用,乙個指向前乙個元素,乙個指向下乙個元素(即存放直接後繼和直接前驅以及資料)。

arraylist和vector都是使用陣列方式儲存資料,此陣列元素數大於實際儲存的資料以便增加和插入元素,它們都允許直接按序號索引元素。

vector類的所有方法都是同步的(使用了synchronized方法)。可以由兩個執行緒安全地訪問乙個vector物件,但是乙個執行緒訪問vector的話**要在同步操作上耗費大量的時間。通常效能上較arraylist差。

arraylist不是同步的,所以在不需要保證執行緒安全時建議使用arraylist。

hashmap和hashtable都實現了map介面,因此很多特性非常相似。但是,他們有以下不同點:

執行緒是否安全:hashmap是非執行緒安全的,hashtable是執行緒安全的,hashtable內部的方法基本都經過synchronized修飾(如果要保證安全的話就使用concurrenthashmap)。

效率:因為執行緒安全的問題,hashmap要比hashtable效率高一點,一般認為hashtable是乙個被淘汰的類,不要在**中使用它。

對null key和null value的支援:hashmap中,null可以作為鍵,這樣的鍵只有乙個,可以有乙個或多個鍵所對應的值為null,且如果使用hashmap,鍵是自定義的類,就必須重寫hashcode()和equals()方法。但是在hashtable中put進的鍵值只要有乙個null,直接丟擲nullpointerexception。

初始容量大小和每次擴充容量大小的不同:①建立時如果不指定容量初始值,hashtable預設的初始大小為11,之後每次擴充,容量變為原來的2n+1。hashmap預設的初始化大小為16,之後每次擴充,容量變為原來的2倍。②建立時如果給定了容量初始值,那麼hashtable會直接使用你給定的大小,而hashmap會將其擴充為2的冪次方大小。

底層資料結構:jdk1.8之前的hashmap底層是陣列和鍊錶結合在一起使用也就是鍊錶雜湊,jdk1.8以後的hashmap在解決雜湊衝突時有了較大的變化,當鍊表長度大於閾值(預設為8)時,將鍊錶轉化為紅黑樹,以減少搜尋時間。hashtable沒有這樣的機制。

hashset底層就是基於hashmap實現的,hashset的原始碼非常非常少,除了clone()、writeobject()、readobject()是hashset自己不得不實現之外,其他方法都是直接呼叫hashmap中的方法。

hashmap

hashset

實現了map介面

實現了set介面

儲存鍵值對

僅儲存物件

呼叫put()向map中新增元素

呼叫add()向set中新增元素

hashmap使用鍵(key)計算hashcode

hashset使用成員物件來計算hashcode值,對於兩個物件來說hashcode可能相同,所以用equals()方法來判斷物件的相等性

當把物件加入hashset時,hashset會先計算物件的hashcode值來判斷物件加入的位置,同時也會與其他加入的物件的hashcode值作比較,如果沒有相符的hashcode,hashset會假設物件沒有重複出現。但是如果發現有相同的hashcode值的物件,這時會呼叫equals()方法來檢查hashcode相等的物件是否真的相同,如果相同,hashset就不會讓加入操作成功。

如果兩個物件相等,則hashcode一定也是相同的;

兩個物件相等,對兩個equals方法返回true;

兩個物件有相同的hashcode值,它們也不一定是相等的;

綜上,equals方法被覆蓋過,則hashcode方法也必須被覆蓋;

hashcode()的預設行為是對堆上的物件產生獨特值,如果沒有重寫hashcode(),則class的兩個物件無論如何都不會相等,即使這兩個物件指向相同的資料。

==與equals的區別:

==是判斷兩個變數或例項是不是指向同乙個記憶體空間,equals是判斷兩個變數或例項所指向的記憶體空間的值是不是相同;

==是指對記憶體位址進行比較,equals()是對字串的內容進行比較;

==是指引用是否相同,equals()指的是值是否相同。

(暫)為了能讓hashmap訪問高效,儘量減少碰撞,也就是要盡量把資料分配均勻。hash值的範圍值-2147483648到2147483647,前後加起來大概40憶的對映空間,只要雜湊函式對映的比較均勻鬆散,一般應用很難出現碰撞。但問題是乙個40億長度的陣列,記憶體是放不下的。所以這個雜湊值是不能直接拿來用的。用之前還要先做對陣列的長度取模運算,得到的餘數才能用來要存放的位置也就是對應的陣列下標。這個陣列下標的計算方法是「(n-1)& hash」。(n代表陣列長度)。這也就是解釋了hashmap的長度為什麼是2的冪次方。

concurrenthashmap和hashtable的區別主要體現在實現執行緒安全的方式上不同。

底層資料結構:jdk1.7的concurrenthashmap底層採用分段的陣列+鍊錶實現,jdk1.8採用的資料結構跟hashmap1.8的結構一樣,陣列+鍊錶/紅黑二叉樹。hashtable和jdk1.8之前的hashmap的底層資料結構類似都是採用陣列+鍊錶的形式,陣列是hashmap的主題,鍊錶則是主要為了解決雜湊衝突而存在的。

實現執行緒安全的方式(重要):①在jdk1.7的時候,concurrenthashmap(分段鎖)對整個桶陣列進行了分割分段(segment),每一把鎖只鎖容器其中一部分資料,多執行緒訪問容器裡不同資料段的資料,就不會存在鎖競爭,提高併發訪問率。到了jdk1.8的時候已經摒棄了segment的概念,而是直接用node陣列+鍊錶+紅黑樹的資料結構來實現,併發控制使用synchronized和cas來操作。整個看起來就像是優化過且執行緒安全的hashmap,雖然在jdk1.8中還能看到segment的資料結構,但是已經簡化了屬性,只是為了相容舊版本。②hashtable(同一把鎖),使用sybchronized來保證執行緒安全,效率非常低下。當乙個執行緒訪問同步方法時,其他執行緒也訪問同步方法,可能會進入阻塞或輪詢狀態,如使用put新增元素,另乙個執行緒不能使用put新增元素,也不能使用get,競爭會越來越激烈效率越低。

iterator提供了統一遍歷操作集合元素的統一介面,collection介面實現iterator介面,每個集合都通過實現iterator介面中iterator()方法返回iterator介面的例項,然後對集合的元素進行迭代操作。有一點要注意的是:在迭代元素的時候不能通過集合的方法刪除元素,否則會丟擲concurrentmodificationexception異常,但是可以通過iterator介面中的remove()方法進行刪除。

collection

list

set

map

集合學習筆記

1 collection是乙個介面,是高度抽象出來的集合,包含了list和set兩大分支。1 list是乙個有序的佇列,list的實現類有linkedlist,arraylist,vector,stack。1.arraylist,執行緒不安全,底層使用陣列實現的,動態陣列增量為50 查詢快增刪慢。2...

JAVA學習筆記 集合

集合部分注意的問題 1.各個介面的特點 2.遍歷。3.集合能進行的操作。4.其實現類的差異。1.collection介面的實現類中的元素是物件object.集合類 集合可以容納 管理多個物件。list介面 其實現類儲存的元素有順序,元素可以重複,實現類 arraylist。set介面 其實現類儲存的...

List集合學習筆記

asp.net unity開發 net培訓 期待與您交流!集合 1特點 集合中存放的都是物件,長度是不可變的,陣列可以存放基本資料型別,長度不可變。2框架 collection list 元素是有序的,元素可以重複,因為該集合體系有索引,特有的迭代器,listiterator是iterator的子介...