详细解释HashMap中tableSizeFor函数

2022网安保研经验帖 2022网安保研经验 阅读详情

最近在看一些集合的源码,看到HashMap感觉用到了很多移位运算的技巧,看了好一会儿才明白,记一下以免以后再忘了

后面有时间会整理完整的源码

HashMap中有这样一段代码,当初始化HashMap时,如果指定了初始容量initialCapacity,由于哈希桶的数目必须是2的n次幂,因此要把initialCapacity转化为比它大的最小的2的n次幂数,例如initialCapacity = 10 ,那就返回16, initialCapacity = 17,那么就返回32。

 /**
     * Returns a power of two size for the given target capacity.
     */
    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;
    }

以上代码就是转换的代码,首先考虑一下如果我要实现这样一个转换的思路:首先通过一个循环去判断int值的二进制表示中,最高位的1是第几位,然后返回一个最高位+1的的2的幂数,这样需要循环31次,代码如下:

public static int convert(int initialCapacity) {
		int a = 1 ;
		int ans = 1;
		int c = initialCapacity - 1 ;  //减1的目的是避免当initialCapacity = 2^n时,返回结果2^n+1
		for(int i=1;i<31;i++) {
			a = a << 1;
			if((c & a) > 0)
				ans = i;
		}
		return 1 << (ans + 1);
	}

jdk源码的做法是通过5次无符号移位运算以及或运算就得到了这个值,分析一下做法:

n第一次右移一位时,相当于将最高位的1右移一位,再和原来的n取或,就将最高位和次高位都变成1,也就是两个1;

第二次右移两位时,将最高的两个1向右移了两位,取或后得到四个1;

依次类推,右移16位再取或就能得到32个1;

最后通过加一进位得到2^n 。

 

注意,当initialCapacity本身就是2^n时,结果会是2^n+1,为了避免出现这样的情况,在一开始将initialCapacity-1,只要该数不是2^n(10000....),减1不会影响最高位1的位置。

举例说明:

例1

10的二进制是1010,减1就是1001

第一次右移取或: 1001 | 0100 = 1101 ;

第二次右移取或: 1101 | 0011 = 1111 ;

第三次右移取或: 1111 | 0000 = 1111 ;

第四次第五次同理

最后得到 n = 1111  ,返回值是 n+1 = 2 ^ 4 = 16 ;  

例2

16的二进制是10000,减1变为01111,移位取或运算之后,返回的就是16

如果不减1,输入10000,移位取或运算之后得到的是11111,返回的是32

 

 

ENVI学习总结(十二)——基于改进的 CASA 模型反演 NPP 基于改进的 CASA 模型反演 NPP 数据为地理空间数据云提供的 TM 影像,其具体信息如图 1 所示。该实验中所使用的 TM 数据已进行过 QUAC 快速大气校正,来消除大气和光照等因素对地物反射的影响。Landsat 主题成像仪(TM)是 Landsat4 和 Landsat5 携带的传感器,每 16 天扫描同一地区,即 16 天覆盖全球一次。 TM 影像包含 7 个波段,波段 1-5 ... 阅读详情

相关推荐

【软件使用】Calibre部分提参的实战技巧与常见问题解析

本文深入解析Calibre部分提参(Partial Extraction)的实战技巧与常见问题,涵盖PEX、hcell和xcell文件的高级应用。通过实际案例展示如何提升电路仿真效率,解决时钟信号失真等复杂问题,并提供版图设计中的防坑指南,助力芯片设计工程师优化工作流程。

weixin_28717431的博客 162

HashMap之tableSizeFor简单解析

tableSizeFor简单解析一、源码及提前知识了解二、举例理解源码1.出入值为16时1.1第一次对其进行的位运算1.2 第二次对其进行位运算1.3 第三次对其进行位运算1.4 返回结果2.出入值为17时2.1第一次对其进行的位运算2.2第二次对其进行的位运算2.3第三次对其进行的位运算2.4 返回结果三 、总结如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的

qq_43279796的博客 1666

惊呆了!Oracle 11g从入门到放弃的保姆级指南(新手必看)

本文为Oracle 11g数据库新手提供了一份详尽的入门指南。内容涵盖从安装配置、SQL*Plus工具使用、核心的SQL增删改查操作,到事务、索引等进阶概念的解析。文章旨在帮助初学者避开常见陷阱,快速掌握这一经典关系型数据库管理系统的基本操作与核心技能,实现从入门到上手。

ooo22的博客 265

n |= n >>> 1——JDK10的HashMap原理 tableSizeFor(initialCapacity)方法

前言 今天我大儿子在我们房子罚款群里问了一个问题,问题如下: 这个问题的答案是16,hashmap具体的知识,自行百度,知道了hashmap的大概知识之后再看回来我下面说的。 为什么是16呢,因为在hashmap在扩容的时候会对threshold进行判断,size大于等于threshold就扩容。这个threshold就是2的次方数,2的次方数就是2的几次方的意思。threshold取得值,是你设...

太书红叶的博客 3676

LTE信令流程及业务流程

eNB返回E-RAB建立响应消息,E-RAB建立列表信息中包含成功建立的承载信息,E-RAB建立失败列表消息中包含没有成功建立的承载消息。3)当下行数据达到时,网络侧先对UE进行寻呼,随后UE发起随机接入过程,并发起service request过程。用户面:S-GW向eNB发送承载建立请求,包含(IMSI, QoS, TFT, TEID, LBI等)控制面:MME向eNB发送E-RAB建立请求,包含E-RAB ID,QoS,S-GW TEID。3)在S1接口上建立S1承载,在Uu接口上建立数据无线承载。

qq_44390640的博客 4582

SAP开发实战:用FI_DOCUMENT_CHANGE BAPI批量修改FB03凭证抬头和行项目文本(附完整ABAP代码)

本文详细介绍了如何使用SAP的FI_DOCUMENT_CHANGE BAPI批量修改FB03凭证抬头和行项目文本,提供完整的ABAP代码实现方案。通过该BAPI,开发者可以高效完成财务凭证的批量修改,确保数据一致性和审计合规性,显著提升SAP财务模块的运维效率。

weixin_29224589的博客 380

ConcurrentHashMap的该构造方法

public ConcurrentHashMap(int initialCapacity) // 校验初始容量不能小于0 if (initialCapacity < 0) throw new IllegalArgumentException(); int cap = ((initialCapacity >= (MAXIMUM_CAPACITY...

luzhensmart的专栏 623

Spring AI Alibaba实战训练营-16 NL2SQL (自然语言转 SQL)应用开发指南

本文介绍了一个基于AI的智能BI应用开发项目,主要实现自然语言转SQL(NL2SQL)功能,包含对话模块、MCP模块、向量数据管理模块。项目采用Spring AI Alibaba框架,集成通义千问大模型,支持内存向量库和AnalyticDB向量数据库两种存储方案。重点展示了chat模块的三个控制器实现:AnalyticNl2SqlController用于生产环境,SimpleChatController适用于开发测试,Nl2sqlForGraphController支持基于图的复杂对话流程。系统通过将业务知

program哲学 1585

tableSizeFor的理解

看了ConcurrentHashMap和hashMap的源码的时候,发现有一个tableSizeFor的方法,目的是将传进来的参数转变为2的n次方的数值。学习了以后,记录一下 /** * Returns a power of two table size for the given desired capacity. * See Hackers Delight, sec 3.2 */ private static final int tableSizeFor(int c) { int n =

qq_41136578的博客 1万+

2026年数学建模国赛论文排版规范:Word与LaTeX终极对比及模板

提前演练:不要等到比赛开始才第一次使用排版工具。至少在赛前一个月完成1-2篇模拟论文的全流程排版练习。建立检查清单:基于国赛规范制定排版检查清单,在提交前逐项核对——公式编号连续?图表引用准确?参考文献完整?页数不超限?善用模板但不止于模板:模板提供的是起点而非终点。根据自身需求调整宏包配置和样式参数,理解每一行配置的含义。关注评审体验:从评委的视角审视论文——重点内容是否突出?逻辑结构是否清晰?视觉层次是否合理?备份与容错:无论使用何种工具,建立多级备份机制。本地、云端、U盘各存一份,且定期保存历史版本。

YOLO 210

一个非常简单的变分量子分类器 (VQC)

​ 在之前的帖子(这里和这里)中,我已经开始谈论 QML,为什么以及如何学习,从现在开始,我将开始分享我的研究和发现,到目前为止,这些都是非常基本的。​

gongdiwudu的专栏 6208

tableSizeFor方法理解

tableSizeFor方法理解 最近在学习HashMap的一些知识点,感觉tableSizeFor方法很巧妙,特意记录一下 首先看一下tableSizeFor方法源码 static final int tableSizeFor(int cap) { int n = cap - 1; n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |

cheng__yu的博客 2320

【同等学力】01-逻辑符号表达

F(x): x是确诊者,G(x):x有症状F(x): x是老人,G(x):x是宠物,L(x,y): x喜欢y。

super_mochi1 1880

HashMap的hash()方法与tableSizeFor()方法

HashMap源码 hash()方法 这是扰动函数,目的是为了避免碰撞问题 static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } 从上面的方法可以看到key的hash值得计算方法,key的高16位不变,低16位与高16位进行异或操作作为最终的hash值 (h >>&gt

vv的博客 829

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

啊哈瞬间之tableSizeFor函数

导读:我记得在《编程珠玑》一书中,作者提到了总有一些优秀的编程思想会让人忍不住发出“啊哈”的声音,这有可能是叹为观止,也有可能是恍然大悟。 1. 简介 tableSizeFor是Java的hashmap/concurrenthashmap的源码中比较重要的一个函数,其功能是:返回一个比输入值大或相等的,离该值最近的2的整数次幂。举例:输入值是5,则该函数返回值是8(2的3次幂),输入值是4,则返回4。说实话,在我真正理解这个函数之前,如果你把它的源码放到我面前,让我说出这个函数的功能,我可能真的无法说出.

普普通通程序猿的博客 263

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

hashmap构造函数及初始化

hashmap构造函数 hashmap的构造函数有四种(jdk1.8): 先上源码,然后再一一解释 // 方式一: public HashMap(int initialCapacity, float loadFactor) { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal initial capacity: " +

KuKu_Nao的博客 1105

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

深入理解HashMap(三): 关键源码逐行分析之构造函数

上一篇我们说明了HashMap的hash算法, 说到HashMap在构造时会自动将table设为2的整数次幂. 本篇我们就来聊聊HashMap的构造函数. 本文的源码基于 jdk8 版本. 构造函数 HashMap 共有四个构造函数 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { // 默认初始大小 16 s

a092cc的专栏 229

Java中的STL-HashMap

Java中的STL-HashMap public class HashMap&amp;amp;lt;K,V&amp;amp;gt; extends AbstractMap&amp;amp;lt;K,V&amp;amp;gt; implements Map&amp;amp;lt;K,V&amp;amp;gt;, Cloneable, Serializable JDK1.8是这样定义的HashMap的,这里我有一个问题。AbstractMap实现了M

qq_35170267的博客 684

hashmap 源码解析 new HashMap()

hashmap 源码解析 new HashMap<>(7) hashmap 实例化有四个构造方法 分别是: 默认构造函数: 最常用 public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } 指定初始化大小的 public HashMa...

sessionsong的专栏 826

HashMap指定初始容量的构造函数-基于源码分析

今日主题是源码分析之HashMap指定初始容量的构造函数(以下都是基于jdk1.8)。 HashMap可以指定初始容量大小的构造函数有两个: /** * The maximum capacity, used if a higher value is implicitly specified * by either of the constructors with arg...

天涯~的博客 641

hashmap扩容_HashMap扩容后,元素是如何重新分布的

此篇重点这篇我们将进行代码分析1、有参构造函数是如何创建map对象的2、当元素增多导致扩容之后,元素是如何重新分布的同样,为了方便读者复盘,我截取源码是尽量将行号带上。jdk版本还是1.8结构图再重复一遍,HashMap的底层数据结构为数组+链表+红黑树的结构,放一个HashMap的结构示意图,有个大致印象。解剖思路创建一个有参构造函数,并往其中添加若干元素,直至触发扩容机制为了方便方便计算has...

weixin_39994296的博客 1275

hashmap怎么取值_hashmap原理分析

本文准备从以下几个方面去讲解HashMap:1)HashMap源码详细分析2)HashMap为什么是线程不安全的?3)HashMap和HashTable的区别4)1.7和1.8的HashMap实现区别总结HashMap源码分析一、构造函数让我们先从构造函数说起,HashMap有四个构造方法,别慌1.1 HashMap() // 1.无参构造方法、 // 构造一个空的HashMap,初始容量为...

weixin_39566593的博客 939

关于HashMap的笔记(1)

关于HashMap的笔记 hash():不为空的情况下,与hashCode的高16做异或。 static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } tableSizeFor(...

weixin_43352708的博客 118

hashmap赋值给另一个hashmap_撸啊撸,再次撸HashMap源码,踩坑源码中构造方法!每次都有收获...

原文链接:https://blog.youkuaiyun.com/wildwolf_001/article/details/107207039HashMap系列文章第一篇 HashMap源码中的成员变量你还不懂? 来来来!!!整理好的成员变量源码解析第二篇 撸啊撸,再次撸HashMap源码,踩坑源码中构造方法!!!每次都有收获构造方法构造一个空的 HashMap ,默认初始容量(16)和默认负载因⼦(0.75...

weixin_39829307的博客 491

【数据结构】HashMap1.8源码

HashMap原理解析 关键常量 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; 是数组的长度。默认初始化时的容量(16),必须为2的幂次方 static final int MAXIMUM_CAPACITY = 1 << 30; 最大容量,2^30 static final float DEFAULT_LOAD_FACTOR = 0.75f; 默认负载因子,代表什么时候会进行扩容操作(当到达链表长度的???待补

qq_38872414的博客 265

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

面试官再问你 HashMap 底层原理,就把这篇文章甩给他看

m0_55849656的博客 268
上一篇: JVM学习之类加载过程
下一篇: Java源码阅读之HashMap
sysong13
博客等级 码龄9年 3粉丝 9原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值