HashMap

作者: i小雨 | 来源:发表于2021-03-30 00:56 被阅读0次

成员变量:

1、序列化版本号:

private static final long serialVersionUID = 362498820763181265L;

2、集合的初始化容量:(默认为16)

/**
* The default initial capacity - MUST be a power of two.
*/
//默认为16:1<<4(左移4位)相当于1*24次方
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

问题1:初始化容量为什么是2的n次幂?如果不为2的n次幂会怎么样?

当向HashMap中添加元素的时候,需要根据key的hash值去确定其在数组中的位置,HashMap为了存取高效,尽量减少hash碰撞,就需要尽量把数据分配均匀,每个链表(也可能位红黑树)的长度大致相同。这就需要算法:
这个算法实际上就是取模,hash%length,但是计算机中直接求余的效率不如位运算。所以源码中做了优化,使用:hash&(length-1)按位与,实际上hash%length等于hash&(length-1),前提是length是2的n次幂


但是为什么这样能够均匀分布减少hash碰撞呢?2的n次幂-1实际上就是n个1.
比如:
为2的n次幂:

图片.png
不为2的n次幂:
图片.png

可以发现:如果数组的长度不是2的n次幂,计算出的索引值很特别容易相同(发生hash碰撞),会导致数组的每个位置下的数据量不均匀,个别位置的链表或者红黑树过长,导致效率降低。


问题2:当初始化HashMap的时候指定了容量(比如为10),会怎么样?

HashMap<String,Integer> hashMap = new HashMap<>(10);

根据源码可以发现:如果初始化给的容量不是2的n次幂,最后容量会变成比初始化给定的值大的最小的2的n次幂。
比如给定的10,将会变成16;给定的17,将会变成32

 public static void main(String[] args) throws Exception {

        HashMap<String,Integer> hashMap = new HashMap<>(11);
        Class aClass = hashMap.getClass();
        Method capacity = aClass.getDeclaredMethod("capacity");
        capacity.setAccessible(true);
        System.out.println(capacity.invoke(hashMap));

        HashMap<String,Integer> hashMap2 = new HashMap<>(17);
        Class aClass2 = hashMap.getClass();
        Method capacity2 = aClass2.getDeclaredMethod("capacity");
        capacity2.setAccessible(true);
        System.out.println(capacity2.invoke(hashMap2));

    }
********************************结果:********************************
16
32

3、负载因子,默认为0.75:

static final float DEFAULT_LOAD_FACTOR = 0.75f;

默认容量为16,当容量超过16*0.75=12时会自动扩容

4、集合最大容量(1<<30)2的30次幂:

static final int MAXIMUM_CAPACITY = 1 << 30;

5、当链表的的数量超过8,会转为红黑树:(并且数组的长度大于64,也就是参数7)

static final int TREEIFY_THRESHOLD = 8;

6、当红黑树的数量小于6,会从红黑树转为链表:

static final int UNTREEIFY_THRESHOLD = 6;

7、链表转为红黑树对应的数组长度的最小值:

static final int MIN_TREEIFY_CAPACITY = 64;

相关文章

网友评论

      本文标题:HashMap

      本文链接:https://www.haomeiwen.com/subject/apsswktx.html