今天在阅读 Integer 类的源码的时候,发现了两个比较有意思的方法, 频繁的使用位运算进行左移和右移操作,
分别是 numberOfLeadingZeros 方法和 numberOfTrailingZeros 方法。
这个方法从 JDK 1.5 以后开始出现,主要功能是返回无符号整型 i 的最高非零位前面的 0 的个数。
例如:
无符号整数 24 的二进制表示为 0000 0000 0000 0000 0000 0000 0001 1000,第五位的 1 为最高非零位,那么调用这个方法返回的就是该位以前 0 的个数,为 27。
我们先来看一下这个方法的源码:
public static int numberOfLeadingZeros(int i) {
// HD, Figure 5-6
if (i == 0)
return 32;
int n = 1;
if (i >>> 16 == 0) { n += 16; i <<= 16; }
if (i >>> 24 == 0) { n += 8; i <<= 8; }
if (i >>> 28 == 0) { n += 4; i <<= 4; }
if (i >>> 30 == 0) { n += 2; i <<= 2; }
n -= i >>> 31;
return n;
}
一开始对频繁的移位操作以及移动的位数百思不解,查阅了相关资料后恍然大悟,这是二分法的经典应用,这个方法的思路是在寻找最高非零位的时候采用折半查找,因为 int 类型是 32 位的,所以先右移 16 位,判断左半部分是否为 0,如果为 0 的话,说明 1 在右半部分,然后将 i 左移 16 位为下面的操作做铺垫,因为此时已经确定高 16 位为 0 了,所以左移 16 位只是将最高非零位移到高 16 位上。如果第一个条件成立了,那么右移 24 位就相当于将原先的低 16 位右移 8 位来确定最高非零位是在低 8 位还是高 8 位上,后面的操作类似,不再一一推导了。
n 变量用来存放 0 的个数,在每次的操作中,如果条件成立,那么就用 n 变量加上 0 的个数。
最后的 n -= i >>> 31 是对最后两位数的判断,因为在上一行代码中,只要条件成立就将 n 的值加 2,并没有再往下判断剩下的两位 0 的个数,因为 n 的初始值为 1,所以默认剩下的两位中最后 1 位是 1,因此最后还要判断是到底是哪一位为 1,如果 i >>> 31 为 0,那么说明最后一位为 1,就不需要减了,如果不为 0,说明倒数第二位为 1,就需要减去 1。
例如:
无符号整数 24 的二进制表示为 0000 0000 0000 0000 0000 0000 0001 1000,调用此方法的执行流程如下:
这个方法也是从 JDK 1.5 以后开始出现,主要功能是返回无符号整型 i 的最低非零位后面的 0 的个数。
例如:
无符号整数 24 的二进制表示为 0000 0000 0000 0000 0000 0000 0001 1000,第四位的 1 为最低非零位,那么调用这个方法返回的就是该位以后 0 的个数,为 3。
我们先来看一下这个方法的源码:
public static int numberOfTrailingZeros(int i) {
// HD, Figure 5-14
int y;
if (i == 0) return 32;
int n = 31;
y = i <<16; if (y != 0) { n = n -16; i = y; }
y = i << 8; if (y != 0) { n = n - 8; i = y; }
y = i << 4; if (y != 0) { n = n - 4; i = y; }
y = i << 2; if (y != 0) { n = n - 2; i = y; }
return n - ((i << 1) >>> 31);
}
这两个方法在编码风格上有一点小的出入,但是思想都是一样的,都是采用二分法,推导过程与 numberOfLeadingZeros 类似,就不详细推导了,读者有兴趣可自行推导。
一、Integer类的使用方法 Interger:整数类型 1、属性。 static int MAX_VALUE:返回最大的整型数; static int MIN_VALUE:返回最小的整型数; static Class TYPE :返回当前类型。 例子: System.out.println("Integer.MAX_VALUE: " + Integer.MAX_V...
在上面的两个篇博客中,我们看到String和Integer不同的常量池的变现形式 我们再看一个例子: 结果:false true 一个是对String的操作,一个是对Integer的操作。我们仍 然用反编译的方法:javap -c test 正如:上面代码的33和57行所示的那样: 对于String类型的变量,他们是通过常量池的方式,记录每个独有的...
Java基础-Integer的==和equals方法 1、首先说下 equals 方法: equals 方法接受的参数为 Object 类型 equals(Object obj),首先会判断参数中的对象 obj 是否是 Integer 同类型的对象,如果是同类型的话再判断值是否相同,如果值也相同的话则返回 true, 值不同的话会返回 false,如果 obj 不是 Integer 类型的话,...
基本数据类型包装类用在基本数据与字符串之间进行转换 parseInt(String s, int radix)方法中 radix是将s指定为多少进制数,而parseint方法 转换结果 为十进制数...
关于Integer类中的常用方法: (1)Integer(int value)和Integer(String s) 构造方法 (2)public static int parseInt(String s) 将...
1.highestOneBit方法 传入一个int参数i,返回其二进制最高位1的权值。 若i为正整数,例如i=9,其二进制为1001,最高位1的权值为8,则返回值为8 若i为负整数,最高位1为符号位,返回值为-2147483648 若i为零,返回值为0 源码如下: 解析: 整个过程可以理解为最高1位向右复制,然后将最高2位向右复制,再将最高4位向右复制…… 这样最多经过...
...
在写代码的时候发现Integer也有equals方法。那么它和string的equals方法有什么区别呢? 这是Integer的方法源码: 可以看见是把对比的对象看是不是Integer类型的,是的话就转为int基本类型再用 == 比较,比较的就是数值了。所以来点特殊的。 代码测试: 输出结果: == **********e和f匹配成功*********** == *****...
新人书写,仅做记录,谢谢观看 若有不当之处,还望指正 8、spring动态代理 8.1 动态字节码技术 8.1.1 静态字节码技术 编写.java文件,后编译成class文件 实例化对象时,通过ClassLoader对象将class文件读取到JVM中, 最后在JVM中再次通过ClassLoader对象生成该对象的Class对象,最终通过Class对象实例化成对象 8.1.2 动态字节码技术 运行时...
One 从初学编程就开始用的最基础的一种循环: 输出结果:1,2,3,4,5 Two 数组原型方法:Array.prototype.forEach()。forEach() 方法对数组的每个元素执行一次提供的函数。 语法 参数 callback 为数组中每个元素执行的函数,该函数接收三个参数: currentValue 数组中正在处理的当前元素。 index可选 数组中正在处...