HashMap在JDK1.7是以數組加鏈表的形式組成,JDK1.8后新增了紅黑樹結構,當鏈表大於8並且容量大於64時,鏈表結構會轉成紅黑樹結構。
JDK1.8 之所以會加入紅黑樹是因為當鏈表過長是會嚴重影響HashMap的性能,而紅黑樹具有快速增刪改查的特點。
HashMap源碼中包含了一下幾個常量的定義:
/** * The default initial capacity - MUST be a power of two. * 初始化長度 */ static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16 /** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arguments. * MUST be a power of two <= 1<<30. * 最大長度 */ static final int MAXIMUM_CAPACITY = 1 << 30; /** * The load factor used when none specified in constructor. * 默認擴容加載因子 */ static final float DEFAULT_LOAD_FACTOR = 0.75f; /** * The bin count threshold for using a tree rather than list for a * bin. Bins are converted to trees when adding an element to a * bin with at least this many nodes. The value must be greater * than 2 and should be at least 8 to mesh with assumptions in * tree removal about conversion back to plain bins upon * shrinkage. * 當鏈表長度大於此值且容量大於64時 */ static final int TREEIFY_THRESHOLD = 8; /** * The bin count threshold for untreeifying a (split) bin during a * resize operation. Should be less than TREEIFY_THRESHOLD, and at * most 6 to mesh with shrinkage detection under removal. * 轉換鏈表的臨界值,當元素小於此值時,會將紅黑樹結構轉換為鏈表結構 */ static final int UNTREEIFY_THRESHOLD = 6; /** * The smallest table capacity for which bins may be treeified. * (Otherwise the table is resized if too many nodes in a bin.) * Should be at least 4 * TREEIFY_THRESHOLD to avoid conflicts * between resizing and treeification thresholds. * 最小樹容量 */ static final int MIN_TREEIFY_CAPACITY = 64;
關於加載因子
加載因子也叫作擴容因子,用來判斷什么時候進行擴容,假設加載因子為0.75,HashMap的初始容量為16,當HashMap中有16 * 0.75 = 12個容量時,HashMap就會進行擴容。
如果加載因子越大,擴容發生的頻率就會比較低,占用空間比較小,但是發生hash沖突的幾率會提升,對元素操作時間會增加,運行效率降低;
如果加載因子太小,那么表中的數據將過於稀疏(很多空間還沒用,就開始擴容了),對空間造成嚴重浪費;
而且因為容量默認為2的次方,當加載因子為0.75時,容量和加載因子的乘積為整數。
所以系統默認加載因子取了0.5 -1 之間的0.75.
