Java中 List、Set、Map 之間的區別
小博此篇記錄了開發過程中常用的幾種集合詳解,三者的區別對比均從IDEA
相關層次圖裡面所得知,基於JDK8
,如有錯誤歡迎批評指正。
List(列表)
List
的元素以線性方式儲存,可以存放重複物件,List
主要有以下兩個實現類:
ArrayList
: 長度可變的陣列,可以對元素進行隨機的訪問,向ArrayList
中插入與刪除元素的速度慢。JDK8
中ArrayList
擴容的實現是通過grow()
方法裡使用語句newCapacity = oldCapacity + (oldCapacity >> 1)
(即1.5倍擴容)計算容量,然後呼叫Arrays.copyof()
LinkedList
: 採用連結串列資料結構,插入和刪除速度快,但訪問速度慢。
Set(集合)
Set
中的物件不按特定(HashCode)的方式排序,並且沒有重複物件,Set
主要有以下兩個實現類:
HashSet
:HashSet
按照雜湊演算法來存取集合中的物件,存取速度比較快。當HashSet
中的元素個數超過陣列大小*loadFactor
(預設值為0.75)時,就會進行近似兩倍擴容(newCapacity = (oldCapacity << 1) + 1
)。TreeSet
:TreeSet
實現了SortedSet
介面,能夠對集合中的物件進行排序。
Map(對映)
Map
是一種把鍵物件和值物件對映的集合,它的每一個元素都包含一個鍵物件和值物件。 Map
主要有以下兩個實現類:
HashMap
:HashMap
基於散列表實現,其插入和查詢<K,V>
的開銷是固定的,可以通過構造器設定容量和負載因子來調整容器的效能。LinkedHashMap
:類似於HashMap
,但是迭代遍歷它時,取得<K,V>
的順序是其插入次序,或者是最近最少使用(LRU
)的次序。TreeMap
:TreeMap
基於紅黑樹實現。檢視<K,V>
時,它們會被排序。TreeMap
是唯一的帶有subMap()
方法的Map
,subMap()
HashMap
底層實現:HashMap
底層整體結構是一個數組,陣列中的每個元素又是一個連結串列。每次新增一個物件(put)時會產生一個連結串列物件(Object
型別),Map
中的每個Entry
就是陣列中的一個元素(Map.Entry
就是一個<Key,Value>
),它具有由當前元素指向下一個元素的引用,這就構成了連結串列。
儲存原理:當向HsahMap
中新增元素的時候,先根據HashCode
重新計算Key
的Hash
值,得到陣列下標,如果陣列該位置已經存在其他元素,那麼這個位置的元素將會以連結串列的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾,如果陣列該位置元素不存在,那麼就直接將該元素放到此陣列中的該位置。
去重原理:不同的Key
算到陣列下標相同的機率很小,新建一個<K,V>
放入到HashMap
的時候,首先會計算Key的陣列下標,如果陣列該位置已經存在其他元素,則比較兩個Key,若相同則覆蓋寫入,若不同則形成連結串列。
讀取原理:從HashMap
中讀取(get)元素時,首先計算Key
的HashCode
,找到陣列下標,然後在對應位置的連結串列中找到需要的元素。
擴容機制:當HashMap
中的元素個數超過陣列大小*loadFactor
(預設值為0.75)時,就會進行2倍擴容(oldThr << 1
)。
三者區別
比較 | List | Set | Map |
---|---|---|---|
繼承介面 | Collection | Collection | |
常見實現類 | AbstractList(其常用子類有ArrayList、LinkedList、Vector) | AbstractSet(其常用子類有HashSet、LinkedHashSet、TreeSet) | HashMap、HashTable |
常見方法 | add( )、remove( )、clear( )、get( )、contains( )、size( ) | add( )、remove( )、clear( )、contains( )、size( ) | put( )、get( )、remove( )、clear( )、containsKey( )、containsValue( )、keySet( )、values( )、size( ) |
元素 | 可重複 | 不可重複(用equals() 判斷) |
不可重複 |
順序 | 有序 | 無序(實際上由HashCode決定) | |
執行緒安全 | Vector執行緒安全 | Hashtable執行緒安全 |