欢迎来到代码驿站!

JAVA代码

当前位置:首页 > 软件编程 > JAVA代码

Java源码解析HashMap的tableSizeFor函数

时间:2021-07-28 07:41:36|栏目:JAVA代码|点击:

aka,HashMap的容量大小必须为2的指数,即16,32,64,128这样的值。那么,在构造函数中,如果调用者指定了HashMap的初始大小不是2的指数,那么,HashMap的tableSizeFor函数,会计算一个大于或等于给定参数的2的指数的值。先来看一下tableSizeFor函数的源码,如下

  /**
   * 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;
  }

这里采用的计算方法不太常见。先是对cap-1,然后一直进行右移操作,最后根据n和MAXIMUM_CAPCITY的大小关系,返回一个值。这究竟是如何实现找到一个大于或等于cap的2的指数的值呢?

首先需要解释一下>>>符号。>>>是无符号右移操作,即,右移后,高位补0. 例如二进制的11000101,>>>1后,得到01100010,即不关心符号位,右移后,高位直接补充0. 

还有一个符号是|=,例如n |= n>>>1,这个其实可以翻译为n = n | n>>>1,| 是位或操作,即两个数字按位进行或操作,即,某一位上,只有一个数字的该位为1,该位的结果即为1.

说清楚了两个符号的含义,下面我们开始解释算法的过程。

函数一开始,把cap -1 赋值给n。这里我们先按住不说,稍后回头解释。接下来就是对n的四次变换。举个例,对于

01010000

这个值来说,n>>>1即可得到

00101000

两个数字位或后,得到

01111000

可以这么来看这个事情,最开始的n,总有它的最高位为1. 右移1位后,与n进行位或操作,则结果的最高位和次高位都为1了,也就是得到了2个1,而且是高位的2位都为1了。

那么这时再对n进行n>>>2,再和n进行位或操作,即可得到4个1. 依此类推,n |= n>>>4,即可得到8个1。然后n |= n>>>8,即可得到16个1。然后 n |= n>>>16,即可得到32个1. 当然,后面几步得到多少个1,得需要n的初始值足够大才可以。否则,n右移后可能就位0了,那么在进行位或操作,也只是上一步的值而已。

通过上面的分析,可以知道,进行完n的四次右移然后位或操作后,得到的其实是n的所有为都为1的一个值。那么最后,返回的时候,取的n + 1,那么即可得到一个比n大的2的指数的值。

那么回过头来看看第一步 n = cap -1就明白了,这里是为了处理当cap本身即是2的指数时的情况。

因为计算机进行移位和位或操作十分迅速,所以,这个函数的执行效率其实很高。tableSizeFor函数就是这样快速找到了一个大于等于cap的2的指数的值。

总结

上一篇:详解Mybatis是如何把数据库数据封装到对象中的

栏    目:JAVA代码

下一篇:java list 比较详解及实例

本文标题:Java源码解析HashMap的tableSizeFor函数

本文地址:http://www.codeinn.net/misctech/161983.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有