在这里对源码中Integer的部分位运算方法做一个分析解读。同理,可以比较一下其他Number的子类,对位运算部分的设计和性能有一个理解。

在java中,Integer是int类型的包装类型,占4个字节,共32位。我们按顺序分析如下几个重要的静态方法:

public static int highestOneBit(int i)

功能:返回输入值不为0的最高位保留,其他设置为0的数

举例:输入10(00001010),输出8(00001000)

分析:

(1)i |= (i >> 1);

算数右移1位,左补1位符号位;与原数或运算,赋值给原数,保证为1的最高位和接着的1位都为1。

(2)i |= (i >> 2);

算数右移2位,左补2位符号位;与原数或运算,赋值给原数,保证为1的最高两位和接着的两位都为1。

(3)i |= (i >> 4);

算数右移4位,左补4位符号位;与原数或运算,赋值给原数,保证为1的最高四位和接着的四位都为1。

(4)i |= (i >> 8);

算数右移8位,左补8位符号位;与原数或运算,赋值给原数,保证为1的最高八位和接着的八位都为1。

(5)i |= (i >> 16);

算数右移16位,左补16位符号位;与原数或运算,赋值给原数,保证为1的最高十六位和接着的十六位都为1。(可以想象一下8位二进制10000000,如何才能把8位全部变为1?)

(6)i - (i >>> 1);

逻辑右移1位,左补0,结果就是不为0的最高位变为0,后面全都是1;再用原数减去移位后的结果,即为最终结果。

public static int numberOfLeadingZeros(int i)

功能:统计前导0的个数

举例:输入0x00000080,输出24

分析:

(1)if (i == 0)

return 32;

当输入为0时,前导0的个数是32位,为提高效率,不需要执行后续逻辑直接返回。

(2)int n = 1;

n为待返回前导0的个数,此处赋初始值为1,后续有用。

(3)if (i >>> 16 == 0) { n += 16; i <<= 16; }

逻辑右移16位,左补16位0,也就是在判断高16位的结果:

如果是0,说明高16位全部都是0位,因此结果至少有16个0,将n累加16。接着左移16位,将待判断的32位的低16位变为高16位;

如果不为0,说明高16位有不为0位。

(4)if (i >>> 24 == 0) { n += 8; i <<= 8; }

逻辑右移24位,左补24位0,也就是在判断高8位的结果:

如果是0,说明高8位全部都是0位,因此结果至少有8个0,将n累加8。接着左移8位,将待判断的16位的低8位变为高8位;

如果不为0,说明高8位有不为0位。

(5)if (i >>> 28 == 0) { n += 4; i <<= 4; }

逻辑右移28位,左补28位0,也就是在判断高4位的结果:

如果是0,说明高4位全部都是0位,因此结果至少有4个0,将n累加4。接着左移4位,将待判断的8位的低4位变为高4位;

如果不为0,说明高4位有不为0位。

(6)if (i >>> 30 == 0) { n += 2; i <<= 2; }

逻辑右移30位,左补30位0,也就是在判断高2位的结果:

如果是0,说明高2位全部都是0位,因此结果至少有2个0,将n累加2。接着左移2位,将待判断的4位的低2位变为高2位;

如果不为0,说明高2位有不为0位。

(7)n -= i >>> 31;

逻辑右移31位,左补31位0,也就是在判断高1位的结果:

分别有0、1两种情况。当为1时,减去1,正好将在第(2)步多加的1清0;当为0时,减去0,正好将在第(2)步多加的1匹配正确值。

为什么不判断低1位?

假设要判断的2位在最左端:00(第(6)判断)、01(第(7)判断)、10(第(7)判断)、11(第(7)判断)

假设要判断的2位在最右端:00(第(1)判断)、01(第(7)判断)、10(第(7)判断)、11(第(7)判断)

覆盖所有情况。

public static int bitCount(int i)

功能:统计值为1的个数

举例:输入0101 0101 0101 0101 0101 0101 0101 0101,输出16

分析:

(1)i = i - ((i >>> 1) & 0x55555555);

以2位为最小组,分析4种情况。

00=0(1的个数)=>00(i)-00(i逻辑右移1位)=00(结果就是1的个数)=0

01=1=>01-00=01=1

10=1=>10-01=01=1

11=2=>11-01=10=2

根据以上推断,((i >>> 1) & 0x55555555)就是为了得到以2位为最小组的值,由于两位中的高1位受上一位的影响,但又需要必须是0,所以与0x55555555操作,将2位小组的高一位抹为0来符合上述逻辑。

每2位代表1的个数。

(2)i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);

将2位1组相加合并结果至4位一组。

i & 0x33333333 低两位。

(i >>> 2) & 0x33333333高两位,但高阶的两位被前两位影响,因此高2位抹为0

每4位代表1的个数。

(3)i = (i + (i >>> 4)) & 0x0f0f0f0f;

将4位1组相加合并结果至8位一组。

i 低四位

i >>> 4 高四位,因为8位最多8个1,因此可以直接使用低4位表示。

结果& 0x0f0f0f0f,高4位无用,用0抹去。

(4)i = i + (i >>> 8);

将8位1组相加合并结果至16位一组。

i 低8位

i >>> 8 高8位,因为16位最多16个1,因此可以直接使用低8位表示。低8位有效值,高8位无意义。

(5)i = i + (i >>> 16);

将16位1组相加合并结果至32位一组。

i 低16位

i >>> 16 高16位,因为32位最多32个1,因此可以直接使用低8位表示。

(6)i & 0x3f;

因为32位最多32个1,因此可以直接使用低6位表示即可,高位用0抹去。

public static int reverse(int i)

功能:按位反转

举例:输入0x00000080,输出0x01000000

分析:

(1)i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;

(i & 0x55555555) << 12位1组,低位变高位,低位为0

(i >>> 1) & 0x555555552位1组,高位变低位,高位为0

或的结果就是2位1组,高低位互换

(2)i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;

(i & 0x33333333) << 24位1组,低2位变高2位,低位为0

(i >>> 2) & 0x333333334位1组,高2位变低2位,高位为0

或的结果就是4位1组,高2与低2位互换

(3)i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;

同理,8位1组,高4与低4位互换

(4)i = (i << 24) | ((i & 0xff00) << 8) |

((i >>> 8) & 0xff00) | (i >>> 24);

以8位为1组,因为组数已经比较少了,直接逆排序很简单

java中的mod运算_Java源码中Integer类位运算分析相关推荐

  1. JDK源码解析 Integer类使用了享元模式

    JDK源码解析 Integer类使用了享元模式. 我们先看下面的例子: public class Demo {public static void main(String[] args) {Integ ...

  2. java lock可重入_Java源码解析之可重入锁ReentrantLock

    本文基于jdk1.8进行分析. ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock. 首先看一下源码中对ReentrantLock的介绍. ...

  3. android 源码中的单例,Android源码中的一种单例实现

    单例模式的实现方式有懒汉,饿汉,双重校验锁,枚举,内部类等等,写法就不全部列举了.Android源码中有一个单例辅助类/frameworks/base/core/java/android/util/S ...

  4. html中图片的属性优化,源码中图片seo优化的技巧是什么

    Seo网站站内结构优化,html中有关图片alt属性与h1标记的优化细节技巧,内蒙古网络营销师蒋元今天可大家一起来聊一下吧! SEO优化,相信大家都觉得优化的每个点都不陌生,但往往在优化过程中却忽略的 ...

  5. sqlmap中的php,python - sqlmap源码中的一个问题

    我最近在使用sqlmap时总是遇到[error]user quit的报错.重装了sqlmap也一样.源码处定位到了报错信息,但还是看不懂报错原因.求大神指教.(和图片上sqlmap报错无关,不管是什么 ...

  6. integer 最大值_JAVA源码之Integer

    一.Integer结构 Integer继承Number类,实现Comparable接口 基本数据类型的包装类除了Character和Boolean没有继承Number外,其它的都继承了 Number ...

  7. java方法注释都英文_JDK源码中的英文注释翻译(Class)

    public final class Class implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement ...

  8. android 设备驱动 位置,android中各个部件驱动在源码中的位置

    Android的专用驱动:Ashmem.binder.logger Ashmem:匿名共享内存驱动 Logger:轻量级的log驱动 Binder:基于OpenBinder驱动,为android平台提 ...

  9. 【深入设计模式】装饰模式—什么是装饰模式?装饰模式在源码中的应用

    文章目录 1. 装饰模式 1.1 装饰模式简介 1.2 装饰模式结构 1.3 装饰模式示例 2. 装饰模式在源码中的应用 2.1 装饰模式在 JDK 中的应用 2.2 装饰模式在 MyBatis中的应 ...

最新文章

  1. 【Python】百度翻译的爬虫实现(前篇)
  2. 【linux基于Postfix和Dovecot邮件系统的搭建】
  3. 151. Leetcode 剑指 Offer 14- I. 剪绳子 (贪心算法-基础题目)
  4. python3接口自动化测试_【python3+request】python3+requests接口自动化测试框架实例详解教程...
  5. GitHub博客开发上线实战
  6. c++ 高效入门_导学三章_第2章_强哥学Py_Python二级通关与实用入门_17讲
  7. java properties $,如何引用java.util.Properties中的另一个属性?
  8. java输出流文件_Java文件输入输出流(封装类)
  9. 【转】在淘宝一年测试工作的感悟
  10. 从wireshark 抓包中的导出 H.264 变成可用暴风直接播放的H264 裸码流文件
  11. 存储器的概述——DRAM动态存储器
  12. 计算机保研面试英文,计算机保研面试英文自我介绍范文
  13. COVID-19 疫苗:在你接种疫苗之后
  14. 50天50个页面-DAY1-Expanding Card
  15. 囚徒困境困境_所以你现在看到了社会困境
  16. arduino nano电路图
  17. rac 火星舱如何备份oracle_火星舱cdp功能-rpo与rto可以做到什么程度
  18. 11对战平台服务器怎么修改,11对战平台无法登陆的解决方法
  19. 浅析Sublabel-Accurate Relaxation of Nonconvex Energies CVPR 2016 Best Paper Honorable Mention
  20. 视频转码工具 HDcinematics Convert 汉化版

热门文章

  1. 你真的需要 @DirtiesContext?
  2. 课程 2B: 制作一款交互性应用
  3. 串行 RapidIO
  4. How can I set ccshared=-fPIC while executing ./configure?
  5. spring 线程安全
  6. SDN时代更需要有保障的网络
  7. sC#进阶系列——WebApi 接口参数不再困惑:传参详解
  8. 关于solaris中 crontab -e 出现数字0的解决办法
  9. [细说Java](3)创建字符串是使用quot; quot;还是构造函数?
  10. httpd glibc free() 报错解决一例