【HashMap】由tableSizeFor想到的一个算法

简介: 【HashMap】由tableSizeFor想到的一个算法
最近在看hashmap的源码,看到一个很有意思的函数,tableSizeFor,不禁想问,这个函数到底做了什么?
    static final int tableSizeFor(int var0) {
        int var1 = var0 - 1;
        var1 |= var1 >>> 1;
        var1 |= var1 >>> 2;
        var1 |= var1 >>> 4;
        var1 |= var1 >>> 8;
        var1 |= var1 >>> 16;
        return var1 < 0 ? 1 : (var1 >= 1073741824 ? 1073741824 : var1 + 1);
    }

我们先把函数源码摆上来,里面出现了几个关键的java运算符
\>>>:按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。
| :如果相对应位都是 0,则结果为 0,否则为 1。
清楚了运算符的作用,我们举例来说明:

var0为7
7的二进制: 0000 0111
var0-1=6 : 0000 0110
var1>>>1 : 0000 0011
var1 |= var1 >>> 1 : 0000 0110
var1 |= var1 >>> 2 : 0000 0111
后续操作结果一样
var1+1 = 8

从这个例子中,我们得出一个结论,这个函数做了以下操作:将原操作数-1,然后将二进制的第一个1之后的所有数变为1,最后返回,操作数+1
那这到底完成了什么功能呢?从上面的分析来看,是为了找出大于等于本身的值的最近的一个2的幂次方值,那为什么刚开始要减去一个1呢?稍等,我们通过另外一个例子说明一下

cap 8
0000 1000

0000 0100 n>>>1

0000 1100 n|n>>>1
0000 0011 n>>>2

0000 1100

0000 1111 n|n>>>2 低位全为1,后续操作结果一样

0000 0001 n+1

0001 0000 16
cap = 15 + 1 = 16

从这个例子上看到,如果原先操作数本身就是2的幂次方,不减去1,直接进行后续操作,那么最后+1之后,肯定会得到大于本身值的下一个2的幂次方。

总结

说到这里,其实大家已经看明白了,这个函数的作用就是为了找出大于等于每个输入值的,最接近的2的幂次方值。不得不说,JDK这里的这个小算法,还是设计挺巧妙的。

目录
相关文章
|
2月前
|
算法 索引
HashMap扩容时的rehash方法中(e.hash & oldCap) == 0算法推导
HashMap在扩容时,会创建一个新数组,并将旧数组中的数据迁移过去。通过(e.hash & oldCap)是否等于0,数据被巧妙地分为两类:一类保持原有索引位置,另一类索引位置增加旧数组长度。此过程确保了数据均匀分布,提高了查询效率。
44 2
|
2月前
|
机器学习/深度学习 算法
让星星⭐月亮告诉你,HashMap之tableSizeFor(int cap)方法原理详解(分2的n次幂和非2的n次幂两种情况讨论)
`HashMap` 的 `tableSizeFor(int cap)` 方法用于计算一个大于或等于给定容量 `cap` 的最小的 2 的幂次方值。该方法通过一系列的无符号右移和按位或运算,逐步将二进制数的高位全部置为 1,最后加 1 得到所需的 2 的幂次方值。具体步骤包括: 1. 将 `cap` 减 1,确保已经是 2 的幂次方的值直接返回。 2. 通过多次无符号右移和按位或运算,将最高位 1 后面的所有位都置为 1。 3. 最终加 1,确保返回值为 2 的幂次方。 该方法保证了 `HashMap` 的数组容量始终是 2 的幂次方,从而优化了哈希表的性能。
34 1
|
6月前
|
存储 算法 Java
Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。
【6月更文挑战第21天】Java查找算法概览:二分查找适用于有序数组,通过比较中间元素缩小搜索范围;哈希查找利用哈希函数快速定位,示例中使用HashMap存储键值对,支持多值关联。简单哈希表实现未涵盖冲突解决和删除操作。
63 1
|
7月前
|
机器学习/深度学习
HashMap中tableSizeFor()方法详解
HashMap中tableSizeFor()方法详解
HashMap中tableSizeFor()方法详解
|
设计模式 算法 Java
面试官:JDK1.8 HashMap扩容rehash算法是如何优化的?
本文跟大家聊一聊一个常见的面试题,那就是JDK1.8 HashMap扩容rehash算法是如何优化的?
|
存储 算法 容器
数据结构算法 - HashMap 源码解析
数据结构算法 - HashMap 源码解析
155 2
数据结构算法 - HashMap 源码解析
|
算法 Java 程序员
Java HashMap 在获得 Key 的 Hash 值的时候用的是什么算法
Java 在 HashMap Key 的 Hash 值的时候用的的是自己 Object 中的 hashCode() 算法。
166 0
|
存储 机器学习/深度学习 算法
算法系列(2)—— 简答一波 HashMap 常见八股面试题
算法系列(2)—— 简答一波 HashMap 常见八股面试题
173 0
算法系列(2)—— 简答一波 HashMap 常见八股面试题
|
存储 算法 程序员
漫画:什么是HashMap? | 算法必看系列二十三
众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。那你知道HashMap默认的初识长度是多少?为什么这么规定?高并发情况下,为什么HashMap可能会出现死锁?在Java8当中,HashMap的结构有什么样的优化?本文将为你深度解读HashMap的灵魂三问!
漫画:什么是HashMap? | 算法必看系列二十三
|
算法
由HashMap哈希算法引出的求余%和与运算&转换问题
1、引出问题   在前面讲解 HashMap  的源码实现时,有如下几点:   ①、初始容量为 1>16   第三步:取模运算:(n-1) & hash 1 static final int hash(Object key) { 2 int h; 3 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); 4 } 5 6 tab[i = (n - 1) & hash];   ps:第 6 行代码是我自己加的。
1399 0