Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制
文章目录
1.HashMap总述
- 无序,线程不安全,效率高;
- 底层结构为数组 + 链表(+ 红黑树);
2.新增结点机制
- 确定数组下标时会对key调用Object.hashCode( ),因此自定义类需要重写hashCode( );
- 确定是否相等时会对value调用Object.equals( ),因此自定义类需要重写equals( );
- 结点判断相等时,会替换结点中的value。
3.数组扩容机制
-
扩容调用底层的resize( )实现,将数组容量扩为2倍;
-
无参构造时,默认的数组容量为16;
-
遇到以下任意一种情况时,便会对数组进行扩容:
– 插入新结点后满足 总结点数 >(数组容量 * 0.75)时,默认的首次扩容时机为:插入第13(16 * 0.75 + 1)个结点之前;
– 插入新结点后 链表长度 > 8 但尝试树化失败(长度 > 8,但不满足数组长度>=64)时。
-
扩容时,创建新的容量为2倍的数组,然后将原数组中的元素重新hash,分配到新数组中。也正是因为扩容流程繁琐,因此建议在创建HashMap对象时使用有参构造减少扩容。
注意:重新hash是指:为链表或红黑树重新分配数组下标:
元素的下标是通过key的hash值与数组容量计算出来的,数组扩容改变了数组容量,因此原来的链表、红黑树就有可能会获得全新的数组下标。
4.链表树化机制(JDK1.8)
-
JDK1.8之后会在满足一定条件时树化链表:调用底层的treefyBin( )实现,将链表转换成红黑树;
-
插入新结点后链表长度 > 8 就会尝试树化:
– 数组长度 < 64,拒绝树化,转而调用resize( )扩容数组;
– 数组长度 >= 64,树化链表;
-
当执行某操作导致红黑树结点数 < 6,红黑树便会退化成链表。
注意:导致红黑树结点数下降有以下两种可能:
- 使用remove( )删除结点后;
- 数组扩容导致重新Hash后