深入扒 HashMap 源码 - 1 各属性解析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/ocp114/article/details/82855840

这里的 jdk 环境是 1.8 会和 1.7 的有区别
一、static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

默认初始化容量,值为 16,实例化 HashMap 时也可以通过 new HashMap<String, Object>(需要的容量); 来指定容量

二、static final int MAXIMUM_CAPACITY = 1 << 30;

默认最大容量,值为 1073741824,是 int 最大值的一半

三、static final float DEFAULT_LOAD_FACTOR = 0.75f;

默认装载因子,值为 0.75f,HashMap 在实例化时如果没有指定装载因子,则会使用这个,但只会在第一次实例化的时候用到,用于计算第一次扩容时需要达到的元素数量,0.75f 意思是指元素数量达到总容量的 75% 时扩容

四、static final int TREEIFY_THRESHOLD = 8;

HashMap 每个桶中的数据由链表树化的阈值,当桶中元素数量超过这个值 并且总容量超过 64(MIN_TREEIFY_CAPACITY)时链表会转化为红黑树,否则桶中的元素数量仅仅大于 TREEIFY_THRESHOLD 的话,只会对哈希表进行 resize() 扩容,至于为什么要树化呢?因为当有大量的数据产生 hash 碰撞,原来 jdk 1.7 中用链表的形式储存数据查询会非常慢,这里用红黑树的形式就快了很多

五、static final int UNTREEIFY_THRESHOLD = 6;

HashMap 桶中元素的数量小于等于 6 的时候,如果原来是树的话,会退化成链表

六、static final int MIN_TREEIFY_CAPACITY = 64;

扫描二维码关注公众号,回复: 3485311 查看本文章

最小树化容量,当桶中元素数量超过这个值 并且总容量超过 64(MIN_TREEIFY_CAPACITY)时链表会转化为红黑树,否则桶中的元素数量仅仅大于 TREEIFY_THRESHOLD 的话,只会对哈希表进行 resize() 扩容

七、transient Node<K,V>[] table;

HashMap 内部重要的属性,用于存放加进来的元素,结构为数组,数组中的元素是链表或者红黑树

八、transient Set<Map.Entry<K,V>> entrySet;

这是 HashMap 内部维护的一个属性,调用 HashMap 的 entrySet() 方法可以获取到,用来遍历的话效率会比较高,相当于 HashMap 对外映射出来的一个视图,比一个个迭代遍历当然会快

九、transient int size;

当前 HashMap 中元素个数,不是容量哦,外部调用 size() 方法时得到的值就是这个

十、transient int modCount;

  1. 执行 put(K key, V value) 时,也就是添加元素时会自增 1
  2. 执行 remove(Object key) 或 remove(Object key, Object value) 时,也就是移除元素时会自增 1
  3. 执行 clear() 时,也就是清除 HashMap 时会自增 1
  4. 执行 forEach(BiConsumer<? super K, ? super V> action) 时会赋值给一个局部变量,最后会和这个局部变量作对比,不相等则抛异常,所以是用来判断线程安全的
  5. 执行 replaceAll(BiFunction<? super K, ? super V, ? extends V> function) 时同上
  6. 在几个内部类中同样会用到这个变量,同样的用途都是为了多线程操作同一个 HashMap 时的安全性

十一、int threshold;

  1. 扩容阈值,用于和 HashMap 的容量比较,当 size > threshold 时扩容
  2. 在默认参数下第一次扩容的时候,
        threshold = DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY,也就是 threshold = 0.75 * 16 = 12
    但是如果以指定容量的方式实例化 HashMap,第一次扩容的时候
        threshold = 容量 * loadFactor
  3. 以后每次扩容都会翻倍
  4. 最后就是当容量达到 1073741824(MAXIMUM_CAPACITY)时,会扩容到 Integer.MAX_VALUE,也就是 2147483647
  5. 所以理论上 HashMap 的最大容量是 2147483647
  6. 要注意的是 threshold 并不会根据 size 的减小而变小,也就是只会不断往上涨

十二、final float loadFactor;

  1. 装载因子,与扩容相关的参数之一
  2. 在第一次实例化 HashMap 时,构造方法中有可选参数 loadFactor,不指定的话会默认 loadFactor = DEFAULT_LOAD_FACTOR
  3. 当容量小于 16(DEFAULT_INITIAL_CAPACITY)或者扩容后大于1073741824(MAXIMUM_CAPACITY)时也会用到,所以并不是每次扩容都会用到

jdk 1.8 中 HashMap 的数据结构
HashMap 的数据结构

猜你喜欢

转载自blog.csdn.net/ocp114/article/details/82855840
今日推荐