> 文档中心 > Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制

Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制

文章目录

  • 1.HashMap总述
  • 2.新增结点机制
  • 3.数组扩容机制
  • 4.链表树化机制(JDK1.8)

1.HashMap总述

  • 无序,线程不安全,效率高;
  • 底层结构为数组 + 链表(+ 红黑树)

Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制

Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制

2.新增结点机制

  • 确定数组下标时会对key调用Object.hashCode( ),因此自定义类需要重写hashCode( );
  • 确定是否相等时会对value调用Object.equals( ),因此自定义类需要重写equals( );
  • 结点判断相等时,会替换结点中的value。

Java基础 | 14.HashMap新增结点机制、数组扩容机制、链表树化机制

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