Java的hashMap桶开链变tree的机制


why:

  在 JDK7 及之前的版本,HashMap 的数据结构可以看成“数组+链表”;

  在 JDK8 及之后的版本,数据结构可以看成"数组+链表+红黑树";

how:

  JDK8中,桶的链表长到一定长度后,会尝试变树。具体代码如下:

    static final int TREEIFY_THRESHOLD = 8;

    static final int MIN_TREEIFY_CAPACITY = 64;

    其中,putval中的“for (int binCount = 0; ; ++binCount)”,就是遍历桶对应的链中,是否包含了put的key,如果没有,则加到链尾,否则不加。

   从代码中可以看出:当一个桶中的链表大于等于TREEIFY_THRESHOLD-1就会尝试进行树型化,在调用treeifBin后直接就与“数组的最小数容量”进行比较,如果小于最小数容量就只进行扩容(目的:个人认为就是放大桶,从而减少冲突)。

extend:

  解决hash冲突的方式有:

    1、上面的“hash+开链”;

    2、开放地址法(线性探测再散列、二次探测再散列、伪随机探测再散列):当冲突发生时,在散列表中形成一个探测序列,沿此序列逐个单元地查找。如果是插入的情况,在探查到开放的地址,则可将待插入的新结点存入该地址单元;如果是查找的情况,探查到开放的地址则表明表中无待查的关键字,即查找失败;

    3、再哈希法:产生冲突时,使用另外的哈希函数计算出一个新的哈希地址、直到冲突不再发生;

    4、建立一个公共溢出区:把冲突的记录都放在另一个存储空间,不放在表里面;