1) & hash

在上一篇 Java 中HashMap详解(含HashTable, ConcurrentHashMap) 中提到在map.put(key, value)的过程中,计算完key的hash值, 是通过hash & (n-1)来得出该元素在Node数组中的下标的,其中n是Node数组的长度。 其实我们更容易想到的是hash % n,这样刚好会得到0~n-1之间的数字,可以用作数组下标。那么为何此处是用的位运算呢?

先说结论。 这里有一个 前提,那就是HashMap中Node数组的长度始终保持是 2^n, 比如默认的16, 如果创建HashMap的时候指定了初始的capacity,而这个capacity可能不是2^n, 会在内部转化一下,得到一个大于这个capacity的最小的2^n的数字来初始化数组。 每次扩容的时候也是进行2倍的扩容。

在这个前提下,hash & (n-1) 与 hash % n 是 等价的。 而位运算更快一些。

先来看一组数字:

n (格式为2^m=十进制数字=二进制数字) n-1 (格式为2^m – 1=十进制数字=二进制数字) 2^2 = 4 = 100 2^2 – 1 = 3 = 011 2^3 = 8 = 1000 2^3 – 1 = 7 = 0111 2^4 = 16 = 10000 2^4 – 1 = 15 = 01111 2^5 = 32 = 100000 2^5 -1 = 31 = 011111

此处我们可以看到规律,2^m的二进制就是1的后面加上m个0, 而2^m -1的二进制就是0的后面加上m个1.

下面我们来看 hash % n(求余数)的运算:

首先看hash/n,由于n=2^m, 我们先看hash/2的情况,这样一来就简单了,因为我们都知道,二进制的情况下,一个数字除以2其实就是右移一位,在左边加一个0,右边移出去一位。如果觉得不好理解,就类比十进制的数字除以10的情况,是一样的。举一反三一下,hash/4的情况自然就是右移2位, 由于n=2^m, 其实hash/n的操作就是右移m位

右移之后我们得到的是hash/n的整除,那么余数呢?其实就是我们移出去的数字

举个例子,假设hash = 18, n=4,我们知道18/4=4 , 18%4 =2,看看按照我们上面的运算是否会得到相同的结果:

18=10010, 4=2^2

1 0 0 1 0 右移2位 0 0 1 0 0 1 0 hash=18 数组长度n=4=2^2 18/4得到的整除 余数18%4

通过运算可以很容易的验证18/4 = 00100 = 4 , 而18%4 = 10 = 2, 是正确的。

现在假设Node数组进行了扩容n=8,再来看一下:

Original: https://www.cnblogs.com/adeline-tech/p/16701991.html
Author: adeline.pan
Title: 1) & hash

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/642628/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • HTTPWeb安全

    验证安全机制 会话管理机制 SQL注入原理 SELECT * FROM test.user WHERE username=” or 1=’1′ and password=’any…

    技术杂谈 2023年7月24日
    067
  • 编程思想与算法leetcode_分治算法详解

    一、基本概念 在计算机科学中,分治法是一种很重要的算法。字面上的解释是”分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更…

    技术杂谈 2023年7月25日
    062
  • HashMap详解

    什么是HashMap容器 【1】HashMap是使用频率最高的用于映射(键值对)处理的数据类型。随着JDK(Java Developmet Kit)版本的更新,JDK1.8对Has…

    技术杂谈 2023年7月24日
    070
  • 如何给自己的网站接入在线客服系统代码

    如何给自己的网站接入在线客服系统代码? 在线客服系统的接入都挺简单的,一般都是通过在网页html中添加带有在线客服功能的js代码来实现的。以唯一在线客服系统的接入步骤为例,给大家做…

    技术杂谈 2023年6月1日
    074
  • crash命令 —— waitq

    参考:https://crash-utility.github.io/help_pages/waitq.html 用法: 查看等待队列中被阻塞的进程 waitq <等待队列地…

    技术杂谈 2023年5月30日
    087
  • Linux入门命令

    命令入门 命令提示符详解 find cut sort wc sed aws [root@localhost ~]# # /root [lilei@node1 ~]$ #/home/…

    技术杂谈 2023年7月11日
    049
  • wordpress模板修改及函数说明

    原文:http://java-er.com/blog/wp-mb-edit/ style.css : CSS(样式表)文件index.php : 主页模板archive.php :…

    技术杂谈 2023年6月1日
    099
  • 「Elasticsearch」SpringBoot快速集成ES

    Elastic Search 的底层是开源库 Lucene。但是Lucene的使用门槛比较高,必须自己写代码去调用它的接口。而Elastic Search的出现正是为了解决了这个问…

    技术杂谈 2023年7月24日
    057
  • 数据库事务知识整理

    什么是数据库事务? 事务,就是一系列操作的整体,其结果就是这一系列操作要么全部成功,要么全部失败。 譬如说,一个经典的例子–转账。A要转帐给B 100块钱,要经历以下步…

    技术杂谈 2023年7月11日
    054
  • JavaCV推流实战(MP4文件)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kuberne…

    技术杂谈 2023年7月11日
    054
  • 1维线性回归

    w= 1.0595238095237538 b= -117.79761904760 undefined Original: https://www.cnblogs.com/canx…

    技术杂谈 2023年7月10日
    057
  • FLASH CS4 制作渐变 动画 有补间动画 传统补间

    下了个FLASH CS4 ,也许太久没玩FLASH了,很多东西都物是人非了,要弄个动画渐变一直不成功。 点来点去,发现有个”添加传统补间”,试一下,可以进行…

    技术杂谈 2023年7月10日
    061
  • JAVA基础学习第三天!

    精华笔记: 1.运算符: -算术:+、-、*、/、%、++、– -关系:>、 -逻辑:&&、||、! -赋值:=、+=、-=、*=、/=、%= -…

    技术杂谈 2023年7月11日
    090
  • 数字数组

    3、【剑指Offer学习】【面试题03:找出数组中重复的数字】 4、【剑指Offer学习】【面试题04:二维数组中的查找】 11、【剑指Offer学习】【面试题11:旋转数组的最小…

    技术杂谈 2023年6月21日
    072
  • Java中方法的定义和使用

    方法的定义和使用 注意事项: 1.方法与方法之间是 平级关系 不可以嵌套定义 2.方法的位置 可以在类{}中任意位置 3.方法定义之后 之后被调用 才能被执行 4.return 关…

    技术杂谈 2023年6月21日
    077
  • [python]-分割结果可视化

    常常会遇到需要将分割的结果可视化的问题,这里采用修改dataset的方式,传入原图路径,最终保存的图片是在原图上叠加分割的结果,可以根据需要修改颜色。注意:这里的颜色三元组顺序是B…

    技术杂谈 2023年7月10日
    061
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球