原来HashMap是这样的

172 阅读1分钟

hashmap是真的需要静下心来仔细看看的

1、核心的几个结构

static final float DEFAULT_LOAD_FACTOR = 0.75f; //加载因子,基于空间和查询的综合考虑
static final int TREEIFY_THRESHOLD = 8;    //链表转换为红黑树的条件之一
static final int UNTREEIFY_THRESHOLD = 6;   //红黑树退化为链表的条件
static final int MIN_TREEIFY_CAPACITY = 64;//链表转换为红黑树的条件,小于此参数进行resize操作
transient Node<K,V>[] table;  // 数组结构 transient int size; //hashmap中元素的个数
transient int modCount;  //修改次数,fast-fail 的实现基于这个变量
final float loadFactor;  //加载因子,新增这个变量减少hash碰撞


Node节点的数据结构如下

Node{
  T t;
  Node prev;
  Node next;
}



2、核心的方法

2.1、putVal

可能存在的问题:

  • put操作时,tab[index]不存在
  • put操作时,key值重复,覆盖 or 直接返回
  • put操作时,put的是红黑树
  • put节点时,put的是链表,这是需要考虑是否进行
jdk8中的实现思路图:


2.2、getNode

设计流程





3、常见问题:

3.1、resize时机?

主要在三个方面

  • 数组为0的时候的进行初始化,默认的table.length为16
  • 数组的容量超过threshold,进行扩容,原长度<<1
  • 链表的长度超过treeifbin变量(默认为8),且小于MIN_TREEIFY_CAPACITY(默认64)

3.2、为啥resize 必须为2的n次方?

 原因如下:

  •  hash % (2<<i -1)的值刚好对应数组下标,对2的n次幂求余有这种性质
  • resize的时候移动的元素相对会减少,resize的时候只多增加了一位