写点什么

HashMap 源码解析一、构造函数,kotlin 插件

用户头像
Android架构
关注
发布于: 刚刚

前两个没什么好讲的,我们直接看第 3 个 HashMap(int initialCapacity, float loadFactor)


这里的重点就是 int tableSizeFor(int cap)函数。

tableSizeFor(int cap) 函数

tableSizeFor(int cap) 的作用是返回 大于等于 cap 且 最接近 cap 的 2 的幂次方的值


static final int MAXIMUM_CAPACITY = 1 << 30;/**


  • Returns a power of two size for the given ta


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


rget capacity.


  • 返回 大于等于 cap 且 最接近 cap 的 2 的幂次方的值*/static final int tableSizeFor(int cap) {int n = cap - 1;n |= n >>> 1;n |= n >>> 2;n |= n >>> 4;n |= n >>> 8;n |= n >>> 16;return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}


我们分步骤解析一下这个函数:


  1. >>> 无符号右移运算符,高位用 0 填充。如下:


a = 1010a >>> 1 = 0101


  1. | 如果相对应位都是 0,则结果为 0,否则为 1。如下:

a = 1010b = 0011

a | b = 1011


  1. |= , a |= b 等同于 a = a|b


这时候我们就能看懂 n |= n >>> 1; 等同于 n = n | n >>> 1


  1. int n = cap - 1; 是因为如果 cap 不减 1,当 cap 本来就是 2 次幂数值,就会导致返回的结果为 cap*2 。

  2. 我们带入一个值看下运行结果,假设 cap = 20


static final int tableSizeFor(int cap) {System.out.println("cap = "+ Integer.toBinaryString(cap));int n = cap - 1;System.out.println("n = "+ Integer.toBinaryString(n));n |= n >>> 1;System.out.println("n1 = "+ Integer.toBinaryString(n));n |= n >>> 2;System.out.println("n2 = "+ Integer.toBinaryString(n));n |= n >>> 4;System.out.println("n4 = "+ Integer.toBinaryString(n));n |= n >>> 8;System.out.println("n8 = "+ Integer.toBinaryString(n));n |= n >>> 16;System.out.println("n16 = "+ Integer.toBinaryString(n));System.out.println("n+1 = "+ Integer.toBinaryString(n+1));return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;}


@Testpublic void tableSizeForTest(){System.out.println("tableSizeFor:"+ tableSizeFor(20));}


我这里直接把 tableSizeFor(int cap) 拷贝出来,然后添加了日志。结果如下:


cap = 10100n = 10011n1 = 11011 (10011 | 01001)n2 = 11111 (11011 | 01101)n4 = 11111 (11111 | 01111)n8 = 11111 (11111 | 01111)n16 = 11111 (11111 | 01111)n+1 = 100000 (11111 + 1)tableSizeFor:32

HashMap(Map<? extends K, ? extends V> m) 构造函数

我们来看下最后一个构造函数,参数是一个 Map ,loadFactor 设置为默认的 0.75,然后 putMapEntries(m, false) 函数,把参数 Map 的值拷贝到构造的 HashMap 中去。


接着我们看下 putMapEntries(m, false) 这个函数的具体实现

putMapEntries(m, false) 函数

/**


  • 在 putAll 和 构造函数 中被调用

  • @param m the map

  • @param 构造函数调用是传 false,否则传 true*/final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {int s = m.size();if (s > 0) {if (table == null) { // 构造函数调用是 table = nullfloat ft = ((float)s / loadFactor) + 1.0F;int t = ((ft < (float)MAXIMUM_CAPACITY) ?(int)ft : MAXIMUM_CAPACITY);if (t > threshold)

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
HashMap 源码解析一、构造函数,kotlin插件