HashMap 源码解析一、构造函数

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

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

  • Returns a power of two size for the given target 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 = 1010
a >>> 1 = 0101

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

a = 1010
b = 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;
}

@Test
public void tableSizeForTest(){
System.out.println(“tableSizeFor:”+ tableSizeFor(20));
}

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

cap = 10100
n = 10011
n1 = 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 = null
    float ft = ((float)s / loadFactor) + 1.0F;
    int t = ((ft < (float)MAXIMUM_CAPACITY) ?
    (int)ft : MAXIMUM_CAPACITY);
    if (t > threshold)
    threshold = tableSizeFor(t);
    }
    else if (s > threshold)
    resize();
    for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
    K key = e.getKey();
    V value = e.getValue();
    putVal(hash(key), key, value, false, evict);
    }
    }
    }
    可以看到,当构造函数调用putMapEntries(Map<? extends K, ? extends V> m, boolean evict) 函数时,通过参数map 的size 设置threshold ,然后调用putVal() 函数设置内容。putVal() 我们在后面讲 put 的时候再具体分析。

小结

我们看完HashMap 的构造函数,可以知道他们的主要作用就是 设置loadFactorthreshold

  • loadFactor 负载因子, 一般都不会设置,默认为0.75
  • threshold 扩容伐值,使用 initialCapacity或者 map.size 通过tableSizeFor(int cap) 函数得到。为大于等于且最接近的2的幂次方的值

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

如何成为Android高级架构师!

架构师必须具备抽象思维和分析的能力,这是你进行系统分析和系统分解的基本素质。只有具备这样的能力,架构师才能看清系统的整体,掌控全局,这也是架构师大局观的形成基础。 你如何具备这种能力呢?一是来自于经验,二是来自于学习。

架构师不仅要具备在问题领域上的经验,也需要具备在软件工程领域内的经验。也就是说,架构师必须能够准确得理解需求,然后用软件工程的思想,把需求转化和分解成可用计算机语言实现的程度。经验的积累是需要一个时间过程的,这个过程谁也帮不了你,是需要你去经历的。

但是,如果你有意识地去培养,不断吸取前人的经验的话,还是可以缩短这个周期的。这也是我整理架构师进阶此系列的始动力之一。


成为Android架构师必备知识技能

对应导图的学习笔记(由阿里P8大牛手写,我负责整理成PDF笔记)

部分内容展示

《设计思想解读开源框架》

  • 目录
  • 热修复设计
  • 插件化框架设计

    《360°全方面性能优化》
  • 设计思想与代码质量优化
  • 程序性能优化
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

(img-cFqnWFii-1712278238164)]

  • 程序性能优化
    [外链图片转存中…(img-EBt7TsL9-1712278238165)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值