集合源码分析06——Map——HashMap源码分析

 

 

 

 

 (其实同之前的HashSet的分析差不多,详情可以看之前的)

 

   1.执行构造器语句,初始化加载因子,并且将table表等初始化为null

 public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

 

   

  2.执行put方法,因为是基本数据类型所以先进行一个装箱操作

public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

 

 

 3.

 

 

 

 

 然后计数变量modCount++,return null;第一次结束

 4.与HashSet不同之处就是在e被改变不为null(key值相同)的情况下走这条代码块的时候,value是会被改变的(因为HashSet的value统一是PERSENT所以没什么变化),这里直接走了return oldValue也就没有modCount++了。

 

 

 

  • HashMap扩容和树化机制模拟触发
package test;

import java.util.HashMap;

/**
 * @author 紫英
 * @version 1.0
 * @discription 随便写
 */
public class Test {
    public static void main(String[] args) {

        HashMap map = new HashMap();
        for (int i = 1; i <= 12; i++) {
           map.put(new A(i),"666");
        }
    }
}

class A{
    int i;

    @Override
    public String toString() {
        return "A{" +
                "i=" + i +
                '}';
    }

    public A(int i) {
        this.i = i;
    }
    //为了保证在同一个位置添加索引我们重写hashcode使之返回一个固定值
    @Override
    public int hashCode() {
        return 100;
    }
}

之后我们通过debug的方式来看一下具体的树化机制的触发

  1.可以看到前8次的时候并没有触发扩容机制

 

  2.第九次的时候满足单条链表超过8个数据进行树化,但是由于table的大小并不满足64所以先进行table的扩容

 

  3.第10次再次扩容到64

 

  4.第11次开始树化

 

可以看出数组类型从之前的Node变成了TreeNode

  5.第12次则通过putTreeVal方法来添加

 

这里说明一下,虽然++size写在了判断条件内,但是是每次都走的,只要size超过了临界值(12-24-48-96-192)都会触发扩容机制,与是否在同一条链表上无关

 

 

  临界值是interger的上限 如果节点数超过这个数值(public static final int MAX_VALUE = 2147483647)的话就一直返回原先的表格,即无法再继续添加了

if (oldCap > 0) {
            if (oldCap >= MAXIMUM_CAPACITY) {
                threshold = Integer.MAX_VALUE;
                return oldTab;
            }

 

 

 

 

 

posted @ 2022-01-20 00:13  紫英626  阅读(29)  评论(0编辑  收藏  举报

紫英