首页 > 编程语言 >Java的Integer.bitCount()源码分析

Java的Integer.bitCount()源码分析

时间:2023-11-21 21:46:02浏览次数:47  
标签:存储 01 Java int 个位 源码 Integer 0x55555555 数量

本文部分参考:https://blog.csdn.net/weixin_42092787/article/details/106607426

常规解法

对于统计一个32位的二进制数值当中1的数量这个问题,常规解法如下:

    public int hammingWeight(int n) {
        int count = 0;
        for (int i = 0; i < 32; i++) {
            n >>= i;
            if((n & 1) == 1){
                count++;
            }
        }
        return count;
    }`

jdk实现

上述方法通过移位运算判断每一位是否为1来统计数量。而jdk的内部实现妙不可言:

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

逐行解释:

i = i - ((i >>> 1) & 0x55555555);
目的:对于每2位,存储1的数量。
& 0x55555555的作用:保留奇数位,去除偶数位。
奇数位1的数量:i & 0x55555555
偶数位1的数量:(i >>> 1) & 0x55555555,偶数位右移到奇数位,原偶数位被按位与抹掉。
按理来说,此时i = i & 0x55555555 + (i >>> 1) & 0x55555555,我们猜测此时2种方式结果一样:
原来i:00 01 10 11
移i后:00 00 01 01
i减后:00 01 01 10
可以看到i减后的值巧妙地存储了原i 1的个数。
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
目的:对于每4位,存储1的数量。
做法:在1中每2位已经存储了1的数量。对于每4位,只需要将高2位+低2位即可实现。
这里就是基本做法无需解释。
i = (i + (i >>> 4)) & 0x0f0f0f0f;
目的:对于每8位,存储1的数量。
这里依旧没有选择常规做法,原理如下:
最大存储8个位刚好只需要1000一共4个位,所以无符号右移4位以后可以直接相加,并不会因为进位导致错误。
i = i + (i >>> 8);
目的:对于每16位,存储1的数量。
这里依旧没有选择常规做法,原理如下:
对于每8位而言在上一步中 & 0x0f0f0f0f;已经将高4位全部设置为0,而存储16位只需要5个位(10000),在此之前最多占用了4个位,就算不抹除高8位(& 0x00ff00ff)也不影响。
i = i + (i >>> 16);
目的:对于每32位,存储1的数量。
与上面类似,而存储32位只需要6个位(100000),距离上次清理来说,还有2个位可用(一个8个)。
return i & 0x3f;
最后&是保留最后2(11)+4(1111)=6个位的结果。事实上讨论到这里我们已经知道在6位只用到了100000。

标签:存储,01,Java,int,个位,源码,Integer,0x55555555,数量
From: https://www.cnblogs.com/llzcx/p/17847678.html

相关文章

  • 【Java基础】String类 && StringBuilder类
    String类String类特点字符串底层是字节类型的数组:byte[]Java程序中所有双引号字符串,都是String类的实例(对象)字符串在创建之后,其内容不可更改字符串虽然不可以改变,但是可以被共享(通过字符串常量池)字符串常量池(StringTable)-->当使用双引号创建字符串对象时,会检查常量池中是......
  • 【Java基础】内存分配
    1.栈方法运行时所进入的内存2.堆需要new的引用数据类型会在堆内存中开辟空间并产生地址堆内存中的数据在生命周期结束后会由垃圾回收器不定时回收(C语言需要手动写代码清理释放内存空间)3.方法区字节码文件加载时进入的内存4.本地方法栈(辅助虚拟机)---了解5.寄存......
  • JavaWeb--JSP脚本
     JSP的缺点     ......
  • Java8新特性lambda学习
    Lambda表达式Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。本质:作为函数式接口的实例,没有接口就没意义了.//简单......
  • idea报错Java HotSpot(TM) 64-Bit Server VM warning Options -Xverifynone and -nove
    问题描述我的:IDEA的版本为:2021.3‍最近在使用idea运行SpringBoot时,idea总是显示报错信息,报错信息如下:‍​​‍解决方法‍第一步:选择下图的EditConfigurations‍​​‍第二步:在跳转出的界面中找到Modifyoptions这个选项,点进去‍​​‍第......
  • 基于springboot的校园失物招领系统-计算机毕业设计源码+LW文档
    校园失物招领系统介绍在现代大学校园中,失物招领系统是一个至关重要的组成部分,旨在为学生、教职员工和访客提供便捷的失物招领服务。本文将介绍一个基于SpringBoot的校园失物招领系统,该系统结合了现代技术和用户友好的界面,提供了高效、安全和快速的失物招领流程。系统架构该系统采......
  • 基于Springboot教学管理系统-计算机毕业设计源码+LW文档
    摘 要传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装教学管理系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,教学管理系统的有效运用......
  • java list转字符串常用方法
    使用标准toString()方法List.toString()是最简单的,但它在开头和结尾添加方括号,每个字符串用逗号分隔符分隔。缺点是我们不能用另一个分隔符替换逗号,也不能去掉方括号。publicstaticvoidmain(String[]args){//creatingalistwithstrings.List<String>......
  • 基于vue技术的农业设备租赁系统-计算机毕业设计源码+LW文档
    摘 要使用旧方法对农业设备租赁系统的信息进行系统化管理已经不再让人们信赖了,把现在的网络信息技术运用在农业设备租赁系统的管理上面可以解决许多信息管理上面的难题,比如处理数据时间很长,数据存在错误不能及时纠正等问题。这次开发的农业设备租赁系统对收货地址管理、字典管理......
  • Java字符串分割[split()]和截取[substring()]
    字符串的分割:一般自字符串的分割常用的方法是java.lang包中的String.split()方法,返回是一个字符串数组。语法:publicString[]split(Stringregex,intlimit)参数:regex -- 正则表达式分隔符。limit --分割的份数。比如:需要分割字符串中的每个字符(空格也会被看做字符),split()中......