10 hashmap如何扩容的?

vvEcho 2025-03-04 11:19:31
Categories: Tags:

hashmap的扩容方式在jdk1.7和jdk1.8中不同,以下来分别说明

在jdk1.7中,hashmap是由数组+链表组成的数据结构,默认容量是16,负载因子是0.75也就是四分之三,当数组元素个数超过16*0.75=12时且新加入的元素发生hash碰撞时,就会扩容,扩容为原来的两倍,也就是32;如果后续元素未发生hash碰撞,则不会扩容而是继续往链表中添加,直到超过16个长度;且发生扩容时,会通过transfer()方法将之前的元素重写hash到新的数组中,然后采用头插法将新元素添加到链表头部,原有链表的顺序反转;最后再将原数组对象的引用指向新数组,旧数组置为null等待gc的回收;

在jdk1.8中,hashmap是由数组+链表+红黑树组成的数据结构,默认容量是16,负载因子是0.75也就是四分之三,当数组元素个数超过16*0.75=12时就会发生扩容,扩容为原来容量的两倍32;然后就是进行数据迁移,在进行数据迁移的过程中,jdk1.8采用了元素的高位运算来确定元素的位置,元素的hash & oldCap若为0则元素留在原有的位置,若不为0则新元素的位置为原来的位置+oldCap的位置,即按尾插法追加到新链表的尾部

转链表,链表转红黑树,树退化为链表

在扩容的过程中如果有hash冲突,则会将冲突的元素放到一个链表下;

若链表长度>8且数组长度>64则进一步将链表转换为红黑树;
否则根据现有容量进行扩容,判断依据为当前元素个数是否超过 当前容量+当前容量*0.75,若超过直接扩容为当前容量的2倍

若转换后的红黑树的节点数小于等于6,则重新转换为链表;