List、Map、set的載入因子,預設初始容量和擴容增量

必須往前走發表於2018-01-04

首先,這三個概念說下。初始大小,就是建立時可容納的預設元素個數;載入因子,表示某個閥值,用0~1之間的小數來表示,當已有元素佔比達到這個閥值後,底層將進行擴容操作;擴容方式,即指定每次擴容後的大小的規則,比如翻倍等。

當底層實現涉及到擴容時,容器或重新分配一段更大的連續記憶體(如果是離散分配則不需要重新分配,離散分配都是插入新元素時動態分配記憶體),要將容器原來的資料全部複製到新的記憶體上,這無疑使效率大大降低。

載入因子的係數小於等於1,意指  即當 元素個數 超過 容量長度*載入因子的係數 時,進行擴容。

另外,擴容也是有預設的倍數的,不同的容器擴容情況不同。

List 元素是有序的、可重複

ArrayList、Vector預設初始容量為10

Vector:執行緒安全,但速度慢

    底層資料結構是陣列結構

    載入因子為1:即當 元素個數 超過 容量長度 時,進行擴容

    擴容增量:原容量的 1倍

      如 Vector的容量為10,一次擴容後是容量為20

ArrayList:執行緒不安全,查詢速度快

    底層資料結構是陣列結構

    擴容增量:原容量的 0.5倍+1

      如 ArrayList的容量為10,一次擴容後是容量為16

 

Set(集) 元素無序的、不可重複。

HashSet:執行緒不安全,存取速度快

     底層實現是一個HashMap(儲存資料),實現Set介面

     預設初始容量為16(為何是16,見下方對HashMap的描述)

     載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容

     擴容增量:原容量的 1 倍

      如 HashSet的容量為16,一次擴容後是容量為32

 

構造方法摘要HashSet() 
HashSet(int initialCapacity)
構造一個新的空 set,其底層 HashMap 例項具有指定的初始容量和預設的載入因子(0.75)。
HashSet hs=new HashSet(1);

所以可見 HashSet類,建立物件的時候是可以的制定容量的大小的 ,期中第二個就具有這個工功能。

 

Map是一個雙列集合

HashMap:預設初始容量為16

     (為何是16:16是2^4,可以提高查詢效率,另外,32=16<<1       –>至於詳細的原因可另行分析,或分析原始碼)

     載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容

     擴容增量:原容量的 1 倍

      如 HashSet的容量為16,一次擴容後是容量為32

Hashtable: 執行緒安全

     預設初始容量為11

     載入因子為0.75:即當 元素個數 超過 容量長度的0.75倍 時,進行擴容

     擴容增量:原容量的 1 倍+1

      如 Hashtable的容量為11,一次擴容後是容量為23

 

Class

初始大小

載入因子

擴容倍數

底層實現

Code

是否執行緒安全

同步方式

ArrayList

10

1

1.5倍+1

Object陣列

int newCapacity = oldCapacity + (oldCapacity >> 1)+1;
“>>”右移符號,所以是除以2,所以新的容量是就的1.5倍+1
Arrays.copyOf 呼叫 System.arraycopy 擴充陣列

執行緒不安全

Vector

10

1

2倍

Object陣列

int newCapacity = oldCapacity +
((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
capacityIncrement預設為0,所以是加上本身,也就是2*oldCapacity,2倍大小
Arrays.copyOf 呼叫 System.arraycopy 擴充陣列

執行緒安全

synchronized

HashSet

16

0.75f

2倍

HashMap<E,Object>

add方法實際呼叫HashMap的方法put

執行緒不安全

HashMap

16

0.75f

2倍

Map.Entry

void addEntry(int hash, K key, V
value, int bucketIndex) {
    if ((size >= threshold) && (null !=
table[bucketIndex])) {
        resize(2 * table.length);
        hash = (null != key) ? hash(key) : 0;
        bucketIndex = indexFor(hash, table.length);
    }

    createEntry(hash, key, value, bucketIndex);
}

執行緒不安全

Hashtable

11

0.75f

2倍+1

Hashtable.Entry陣列

int newCapacity = (oldCapacity
<< 1) + 1;
if (newCapacity – MAX_ARRAY_SIZE > 0) {
    if (oldCapacity == MAX_ARRAY_SIZE)
        return;
    newCapacity = MAX_ARRAY_SIZE;
}

執行緒安全

synchronized

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

這是基於jdk1.7版本以前進行研究,jdk1.7以後有所改動

原文地址:https://www.cnblogs.com/lizhen-home/p/7352125.html


相關文章