记一次HashMap面试经历
一、首先说一下HashMap中几个重要参数
即默认桶的数量为16,一般第一次扩容时会扩容到64,之后为2倍的扩容
loadFactor译为装载因子,默认为0.75,装载因子用来衡量HashMap满的程度
最大容量: 2^ 30 次方
树形阈值:JDK 1.8 新增的,当使用 树 而不是列表来作为桶时使用。必须必 2 大,也就是当桶后的链表大于8时,链表会升级为红黑树
非树形阈值:也是 1.8 新增的,扩容时分裂一个树形桶的阈值,要比 TREEIFY_THRESHOLD 小,也就是当链表数到6时,从树形结构退化为链表
二、HashMap是在什么时候的初始化的
HashMap并不是在new的时候直接初始化的,而是在put的时候进行初始化的,可以查看源码如下:
上诉HashMap的构造方法中,只是对传入的容量值和装载因子进行判断是否合法,如果是在构造方法中直接传入一个Map进行初始化的源码中会调用putVal这个方法进行节点创建,而调用put方法,最后也是会调用putVal方法,最后调用resize方法进行初始化。
三、HashMap是怎么保证数据唯一性的呢
hashMap进行put方法放入数据时,会调用进行hash值和equals进行比较,如果都相等,直接覆盖前面的值。
四、hashMap的扩容注意事项
扩容/初始化调用的就是源码中的resize()方法。
扩容过程中几个关键的点:
1.新初始化哈希表时,容量为默认容量,阈值为 容量*加载因子,加载因子用于计算阀值使用
2.已有哈希表扩容时,容量、阈值均翻倍
3.如果之前这个桶的节点类型是树,需要把新哈希表里当前桶也变成树形结构
4.复制给新哈希表中需要重新索引(rehash),这里采用的计算方法是
e.hash & (newCap - 1),等价于 e.hash % newCap
hashMap进行扩容时,需要迭代所有的元素,rehash、赋值,还得保留原来的数据结构,所以性能开销较大,应尽量避免调用resize方法进行扩容。