Java中的Integer.bitCount(i)的返回值是i的二进制表示中1的个数。源码如下:

public static int bitCount(int i) {
// HD, Figure 5-2
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}

源码解析如下:

public static int bitCount(int i) {
// HD, Figure 5-2
/**
* 每两位为一个单元,把原来单元中1的个数储存在原来的单元中
*/
i = i - ((i >>> 1) & 0x55555555);
/**
*0x33333333其实就是二进制……00110011(共32位),因为上面的每两位代表1的个数,所以下面的这几行就是要把上面每两位
* 的数字加起来,下面的这行代码可以这样理解,每4位分为一组,然后4位中的每两位相加,相加的结果在储存到这4位二进制数中,
* i & 0x33333333表示每4位中的低2位,(i >>> 2) & 0x33333333表示每4位中的高2位,然后在相加
*/
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
/**
* 这个更好理解,i >>> 4表示往右移动了4位,然后在与i相加,相当于每8位一组,然后8位中的高4位与低4位相加储存在低4位中,
* 然后这里在与0x0f0f0f0f进行与运算,把高4位完全置为0了,因为0x0f0f0f0f用二进制表示就是00001111000011110000111100001111,
* 看到这里可能有些困惑,这里为什么要与0x0f0f0f0f进行与运算,因为每8位一组的话,最多也就是8,那么4位数足够了,高4位就没有必要了,
* 如果不置为0有没有影响,其实如果1的位数极少的话是没什么影响的,但如果1的位数比较多到后面计算的结果可能就会往前进位,导致结果错误,
* 所以这一步要进行一次与运算,那为什么上面的那行代码没有把4位一组中的高两位置0,这是因为4位一组最多有4个1,而2位二进制数最多表示3,
* 小于4,所以不能置为0,
*
*/
i = (i + (i >>> 4)) & 0x0f0f0f0f;
/**
* 和上面类似,每16位分为一组,每组中的高8位和低8位相加,这里的代码相加的很干净,因为无论是高8位还是低8位中的前4位在上面一行中
* 都已经置为0了,这里也可以像上面那样,加完之后在与0x00ff00ff进行与运算,但其实这里已经没有必要了,因为int类型为32位,
* 最多也就32个1,用8位数储存足够了,所以不会超过8位,也就不用担心超过8位在往前进1位的问题了。
*/
i = i + (i >>> 8);
/**
* 和上面类似,就不在详述
*/
i = i + (i >>> 16);
/**
* 到最后为什么要和0x3f进行与运算,0x3f用二进制表示就是111111,因为上面两行没有进行与运算,所以前面的数据都是无效的,
* 只有最后8位是有效的,而后8位的前两位不用说肯定为0,因为最多也就32个1,用后面6位数表示就已经足够了,所以这里与0x3f
* 进行与运算,来计算出最终1的个数
*/
return i & 0x3f;
}

i=031bi

Java源码解释之Integer.bitCount的更多相关文章

  1. JDK源码学习笔记——Integer

    一.类定义 public final class Integer extends Number implements Comparable<Integer> 二.属性 private fi ...

  2. 从Java源码到Java字节码

    Java最主流的源码编译器,javac,基本上不对代码做优化,只会做少量由Java语言规范要求或推荐的优化:也不做任何混淆,包括名字混淆或控制流混淆这些都不做.这使得javac生成的代码能很好的维持与 ...

  3. java源码——0~9十个数字不重复地使用使加法表达式成立

    这个问题是在我写个的几个博客里较为复杂的一个.首先,先看看整个问题的表述. 星号表示0~9的一个数字,而且不允许重复,使得下面的加法表达式成立.输出所有结果. ※ ※ ※ ※ ※    +  2   ...

  4. Java源码分析 | CharSequence

    本文基于 OracleJDK 11, HotSpot 虚拟机. CharSequence 定义 CharSequence 是 java.lang 包下的一个接口,是 char 值的可读序列, 即其本身 ...

  5. 解密随机数生成器(二)——从java源码看线性同余算法

    Random Java中的Random类生成的是伪随机数,使用的是48-bit的种子,然后调用一个linear congruential formula线性同余方程(Donald Knuth的编程艺术 ...

  6. Java源码解读(一)——HashMap

    HashMap作为常用的一种数据结构,阅读源码去了解其底层的实现是十分有必要的.在这里也分享自己阅读源码遇到的困难以及自己的思考. HashMap的源码介绍已经有许许多多的博客,这里只记录了一些我看源 ...

  7. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...

  8. 24点扑克牌游戏——(含java源码)(GUI实现)

    给出四个数字,要求,在其间添加运算符和括号,使得计算结果等于24. 括号的放置即为决定哪几个数先进行计算.所以,我们先确定首先进行计算的两个相邻的数,计算完成后,就相当于剩下三个数字,仍需要在它们之间 ...

  9. Java源码——String

    最近在研究java的源代码,但是由于自己英语水平有限,所以想使用中文注释的方式把源码里的方法全部重写 一遍,下面是楼主整理出来的一小部分.我把整体的项目托管到GitHub上了,欢迎大家前去交流学习. ...

随机推荐

  1. 爬虫 (4)- Selenium与PhantomJS(chromedriver)与爬取案例

    Selenium文档 Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键精灵,可以按指定的命令自动操作,不同是Selenium 可以直接运行在浏览器 ...

  2. libxl库的介绍,对Excel操作封装得很好的一个库,兼容2007版和多字节字符(最后有破解版下载)

    前段时间忙着毕业论文,终于有时间写博客了. 早些时候老大给我的一个任务需要对excel进行读表操作,研究了一下c++对excel的操作. 对Excel的操作基本有com,ODBC,AD等,其中ODBC ...

  3. Reducing the Dimensionality of Data with Neural Networks

    ****************内容加密中********************

  4. Docker for window 无法共享磁盘

    Docker for window 无法共享主机磁盘,环境如下: 操作系统: windown10 Docker version 18.09.0, build 4d60db4 症状如下: 如图,点击ap ...

  5. Python 构造函数、 Python 析构函数、Python 垃圾回收机制

    构造函数与析构函数 构造函数: 用于初始化类的内容部状态,Python提供的构造函数式 __init__(); 也就是当该类被实例化的时候就会执行该函数.那么我们就可以把要先初始化的属性放到这个函数里 ...

  6. django用户认证系统——注册3

    用户注册就是创建用户对象,将用户的个人信息保存到数据库里.回顾一下 Django 的 MVT 经典开发流程,对用户注册功能来说,首先创建用户模型(M),这一步我们已经完成了.编写注册视图函数(V),并 ...

  7. SharePoint服务器端对象模型 完结

    整个系列已完结,大概看了一眼,平均阅读量不到200.估计也没什么人看了,而且服务器端对象模型除了在某些企业开发中会用到,从2013时代开始其实已经不是SharePoint开发的最佳选择了.不过既然已经 ...

  8. 所有版本chromedriver下载

     所有版本chromedriver下载 http://chromedriver.storage.googleapis.com/index.html

  9. python之MySQL学习——数据操作

    1.增 import pymysql as ps # 打开数据库连接 db = ps.connect(host=', database='test', charset='utf8') # 创建一个游标 ...

  10. 手动爬虫之报头及代理封装类(python3)

    本人刚刚学习爬虫,见每次都需要添加报头比较繁琐,故将该过程封装为Url_ProxyHelper类,代码如下 import urllib.request as ur class Url_ProxyHel ...