java中的mod运算_Java源码中Integer类位运算分析
在这里对源码中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类位运算分析相关推荐
- JDK源码解析 Integer类使用了享元模式
JDK源码解析 Integer类使用了享元模式. 我们先看下面的例子: public class Demo {public static void main(String[] args) {Integ ...
- java lock可重入_Java源码解析之可重入锁ReentrantLock
本文基于jdk1.8进行分析. ReentrantLock是一个可重入锁,在ConcurrentHashMap中使用了ReentrantLock. 首先看一下源码中对ReentrantLock的介绍. ...
- android 源码中的单例,Android源码中的一种单例实现
单例模式的实现方式有懒汉,饿汉,双重校验锁,枚举,内部类等等,写法就不全部列举了.Android源码中有一个单例辅助类/frameworks/base/core/java/android/util/S ...
- html中图片的属性优化,源码中图片seo优化的技巧是什么
Seo网站站内结构优化,html中有关图片alt属性与h1标记的优化细节技巧,内蒙古网络营销师蒋元今天可大家一起来聊一下吧! SEO优化,相信大家都觉得优化的每个点都不陌生,但往往在优化过程中却忽略的 ...
- sqlmap中的php,python - sqlmap源码中的一个问题
我最近在使用sqlmap时总是遇到[error]user quit的报错.重装了sqlmap也一样.源码处定位到了报错信息,但还是看不懂报错原因.求大神指教.(和图片上sqlmap报错无关,不管是什么 ...
- integer 最大值_JAVA源码之Integer
一.Integer结构 Integer继承Number类,实现Comparable接口 基本数据类型的包装类除了Character和Boolean没有继承Number外,其它的都继承了 Number ...
- java方法注释都英文_JDK源码中的英文注释翻译(Class)
public final class Class implements java.io.Serializable, GenericDeclaration, Type, AnnotatedElement ...
- android 设备驱动 位置,android中各个部件驱动在源码中的位置
Android的专用驱动:Ashmem.binder.logger Ashmem:匿名共享内存驱动 Logger:轻量级的log驱动 Binder:基于OpenBinder驱动,为android平台提 ...
- 【深入设计模式】装饰模式—什么是装饰模式?装饰模式在源码中的应用
文章目录 1. 装饰模式 1.1 装饰模式简介 1.2 装饰模式结构 1.3 装饰模式示例 2. 装饰模式在源码中的应用 2.1 装饰模式在 JDK 中的应用 2.2 装饰模式在 MyBatis中的应 ...
最新文章
- 【Python】百度翻译的爬虫实现(前篇)
- 【linux基于Postfix和Dovecot邮件系统的搭建】
- 151. Leetcode 剑指 Offer 14- I. 剪绳子 (贪心算法-基础题目)
- python3接口自动化测试_【python3+request】python3+requests接口自动化测试框架实例详解教程...
- GitHub博客开发上线实战
- c++ 高效入门_导学三章_第2章_强哥学Py_Python二级通关与实用入门_17讲
- java properties $,如何引用java.util.Properties中的另一个属性?
- java输出流文件_Java文件输入输出流(封装类)
- 【转】在淘宝一年测试工作的感悟
- 从wireshark 抓包中的导出 H.264 变成可用暴风直接播放的H264 裸码流文件
- 存储器的概述——DRAM动态存储器
- 计算机保研面试英文,计算机保研面试英文自我介绍范文
- COVID-19 疫苗:在你接种疫苗之后
- 50天50个页面-DAY1-Expanding Card
- 囚徒困境困境_所以你现在看到了社会困境
- arduino nano电路图
- rac 火星舱如何备份oracle_火星舱cdp功能-rpo与rto可以做到什么程度
- 11对战平台服务器怎么修改,11对战平台无法登陆的解决方法
- 浅析Sublabel-Accurate Relaxation of Nonconvex Energies CVPR 2016 Best Paper Honorable Mention
- 视频转码工具 HDcinematics Convert 汉化版
热门文章
- 你真的需要 @DirtiesContext?
- 课程 2B: 制作一款交互性应用
- 串行 RapidIO
- How can I set ccshared=-fPIC while executing ./configure?
- spring 线程安全
- SDN时代更需要有保障的网络
- sC#进阶系列——WebApi 接口参数不再困惑:传参详解
- 关于solaris中 crontab -e 出现数字0的解决办法
- [细说Java](3)创建字符串是使用quot; quot;还是构造函数?
- httpd glibc free() 报错解决一例