Java8源码 java.lang 包 09、Integer类

Integer 类是基本类型 int 的包装类,有着很多和 Byte、Short 类似的方法。同时提供了 int 和 String 之间互相转换的方法,以及很多处理 int 时非常有用的其他方法和常量。

Integer 源码中最大的亮点个人感觉有如下亮点
1、通过对二进制的各种骚操作,从而替代乘除运算
2、通过一些缓存数组来减少运算

类的定义

public final class Integer extends Number implements Comparable<Integer> 

同 Byte、Short。

静态内部类 IntegerCache

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }

IntegerCache表示 Integer 缓存。它也默认保存了-128~127 共 256 个 Integer 包装类对象。和 Byte、Short 的缓存不同之处在于,它可以在 JVM 配置中设置 -XX:AutoBoxCacheMax的值来改变缓存的上限。当然这个设置值要大于等于127且小于 Integer.MAX_VALUE 时才起作用。

Integer i = 100; 编译器会转成 Integer i = Integer.valueOf(100);

成员变量

    private final int value;

用于保存 Integer 对象的 int 值。

类变量

边界值

    @Native public static final int   MIN_VALUE = 0x80000000;	// -2147483648
    @Native public static final int   MAX_VALUE = 0x7fffffff;   //  2147483647

元注解 @Native 是1.8新加入的内容。它表示定义常量值的字段可以被 native 代码引用,当 native 代码和 java 代码都需要维护相同的常量时,如果 java 代码使用了 @Native 标志常量字段,可以通过工具将它生成 native 代码的头文件。简而言之就是表示常量有可能被本地代码引用。

补码相关

    @Native public static final int SIZE = 32;
	// 以二进制补码形式表示 int 值的字节数
    public static final int BYTES = SIZE / Byte.SIZE;

字符数组

    // 用于将数字表示为字符串时的所有可能用到的字符,共36个
	final static char[] digits = {
        '0' , '1' , '2' , '3' , '4' , '5' ,
        '6' , '7' , '8' , '9' , 'a' , 'b' ,
        'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
        'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
        'o' , 'p' , 'q' , 'r' , 's' , 't' ,
        'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };
	
	// 用于获取100以内非负整数的十位
    final static char [] DigitTens = {
        '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
        '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
        '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
        '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
        '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
        '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
        '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
        '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
        '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
        '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
        } ;
	
	// 用于获取100以内非负整数的个位
    final static char [] DigitOnes = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        } ;
	
	// 用于int型数字对应字符串的长度
    final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

构造函数

    // 构造一个新分配的 Integer 对象,它表示指定的 int 值。推荐使用 valueOf 来创建对象
	public Integer(int value) {
        this.value = value;
    }
    
    public Integer(String s) throws NumberFormatException {
        this.value = parseInt(s, 10);
    }

和 Byte、Short 类似。

其他方法

整数转字符串

public String   toString()
public static String   toString(int i)
public static String   toString(int i, int radix)

public static String   toBinaryString(int i)
public static String   toHexString(int i)
public static String   toOctalString(int i)

public static String   toUnsignedString(int i)
public static String   toUnsignedString(int i, int radix)

重写的 toString 方法

    public String toString() {
        return toString(value);
    }

toString(int i)

    public static String toString(int i) {
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        // 保护型构造方法
        return new String(buf, true);
    }

    static int stringSize(int x) {
        for (int i=0; ; i++)
            if (x <= sizeTable[i])
                return i+1;
    }

	final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                      99999999, 999999999, Integer.MAX_VALUE };

  1. 如果是整数的最大负数,则直接返回。

  2. 获取整数数值的长度,若是负数则长度加1。然后创建相同长度的字符数组,便于后续构建字符串数据。

    在这步中,巧妙的使用了 sizeTable 数组来获取长度,避免了除法操作;与此同时,由于空间局部性原理,数组 sizeTable 会被一次性的加载到 cache 中,之后对其访问无需再过内存。

  3. 填充字符数组的内容

    static void getChars(int i, int index, char[] buf) {
        int q, r;
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }
		
        // Generate two digits per iteration	
        // 就是处理高8位, 每次都会将i中的最后两位保存到字符数组buf中的最后两位中
        // 比如65536,循环后 buf[4] = 6,buf[3] = 3,随后循环退出。
        while (i >= 65536) {
            q = i / 100;
        // really: r = i - (q * 100);
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
            buf [--charPos] = DigitOnes[r];	
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        for (;;) {
            q = (i * 52429) >>> (16+3);
            r = i - ((q << 3) + (q << 1));  // r = i-(q*10) ...
            buf [--charPos] = digits [r];
            i = q;
            if (i == 0) break;
        }
        if (sign != 0) {
            buf [--charPos] = sign;
        }
    }

这段代码可以分为4个部分:

  1. 正负数判断,如果是负数,则转正,同时设置符号标识符。如果是正数则不作任何处理
  2. while 循环处理 int 的高 8 位,每次处理两位,使用移位和加分代替乘法。然后在预定义的数组中获取十位数和个位数的数值。DigitOnes[r]; 相当于 r % 10,DigitTens[r]; 相当于 r / 10。
  3. for 循环处理 int 的低 8 位。
    • 用移位和乘法代替除法:q = (i*52429) >>> (16+3) = (i*52429)/524288; 相当于 q = i / 10
    • 用移位和加法代替乘法:((q << 3) + (q << 1)); 相当于 q * 10
    • 然后在预定义的数组 digits 中获取对应的字符
  4. 如果是负数,则在字符数组中填充符号位

这段代码对十进制的处理可以说优化到了极致。通过各种移位来避免使用除法运算,即使是在不得不运用除法的 while 循环中,也是通过每次除以 100 而不是每次除以 10 来减少除法次数。

移位的效率比直接乘除的效率要高;乘法的效率比除法的效率要高

52429、16+3 这些数字是怎么敲定的?

这就触及到知识盲区了o(╥﹏╥)o 可以参考 这位大佬的博客

toString(int i, int radix)

 public static String toString(int i, int radix) {
      	// Character.MIN_RADIX = 2 
     	// Character.MAX_RADIX = 36
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        if (radix == 10) {
            return toString(i);
        }

        char buf[] = new char[33];
        boolean negative = (i < 0);
        int charPos = 32;

        if (!negative) {
            i = -i;
        }

        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }

        return new String(buf, charPos, (33 - charPos));
    }

将 int 型数值转换成指定进制的字符串形式。

  1. 判断进制参数的合法性。如果不在2~36之间则按十进制处理
  2. 如果就是十进制,则返回内部的静态 toString(int i) 方法处理后的结果
  3. 创建一个长度为 33 的字符数组(int类型的二进制需要 32 位,再加上一个负号标识位)。由于 int 的负数比正数大,为了防止溢出,所以全按负数形式来进行辗转相除处理。
  4. 最后返回字符串对象。

转换为其他进制的字符串形式

    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }
    public static String toOctalString(int i) {
        return toUnsignedString0(i, 3);
    }
    public static String toHexString(int i) {
        return toUnsignedString0(i, 4);
    }

    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }

numberOfLeadingZeros 方法返回 int 的二进制补码形式高位中有多少个0。这其实就是二分法,有点秀。

numberOfLeadingZeros(int i)

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

toUnsignedString0 的核心方法是 formatUnsignedInt

static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
    int charPos = len;
    int radix = 1 << shift;
    int mask = radix - 1;
    do {
        buf[offset + --charPos] = Integer.digits[val & mask];
        val >>>= shift;
    } while (val != 0 && charPos > 0);

    return charPos;
}

int radix = 1 << shift;int mask = radix - 1;val & mask,就是在取得 int 变量 val 的低 shift 位。而 Integer.digits[val & mask] 就相当于 val%(mask+1)。在一次循环中完成了一次进制转换。

toUnsignedString

    public static String toUnsignedString(int i) {
        return Long.toString(toUnsignedLong(i));
    }
    
	public static String toUnsignedString(int i, int radix) {
        return Long.toUnsignedString(toUnsignedLong(i), radix);
x    }

字符串转整数

public static Integer getInteger(String nm)
public static Integer getInteger(String nm, int val)
public static Integer getInteger(String nm, Integer val)
public static Integer decode(String nm) throws NumberFormatException

public static Integer valueOf(String s, int radix) throws NumberFormatException
public static Integer valueOf(String s) throws NumberFormatException

public static int parseInt(String s, int radix) throws NumberFormatException
public static int parseInt(String s) throws NumberFormatException
public static int parseUnsignedInt(String s, int radix) throws NumberFormatException
public static int parseUnsignedInt(String s) throws NumberFormatException

getInteger

    public static Integer getInteger(String nm) {
        return getInteger(nm, null);
    }
    
    public static Integer getInteger(String nm, Integer val) {
        String v = null;
        try {
            v = System.getProperty(nm);
        } catch (IllegalArgumentException | NullPointerException e) {
        }
        if (v != null) {
            try {
                return Integer.decode(v);
            } catch (NumberFormatException e) {
            }
        }
        return val;
    }

返回指定名称的系统属性的整数值。 如果字符串参数为 null 或 空 或 是不正确的数字格式,则返回调用 Integer.decode(String) 方法一个表示第二个参数的值的 Integer 对象。
推荐的用法如下,这样可以避免在无需默认值时分配不必要的 Integer 对象:

 Integer result = getInteger(nm, null);
 return (result == null) ? new Integer(val) : result;

decode(String nm)

    public static Integer decode(String nm) throws NumberFormatException {
        int radix = 10;
        int index = 0;
        boolean negative = false;
        Integer result;

        if (nm.length() == 0)
            throw new NumberFormatException("Zero length string");
        char firstChar = nm.charAt(0);
        // Handle sign, if present
        if (firstChar == '-') {
            negative = true;
            index++;
        } else if (firstChar == '+')
            index++;

        // Handle radix specifier, if present
        if (nm.startsWith("0x", index) || nm.startsWith("0X", index)) {
            index += 2;
            radix = 16;
        }
        else if (nm.startsWith("#", index)) {
            index ++;
            radix = 16;
        }
        else if (nm.startsWith("0", index) && nm.length() > 1 + index) {
            index ++;
            radix = 8;
        }

        if (nm.startsWith("-", index) || nm.startsWith("+", index))
            throw new NumberFormatException("Sign character in wrong position");

        try {
            result = Integer.valueOf(nm.substring(index), radix);
            result = negative ? Integer.valueOf(-result.intValue()) : result;
        } catch (NumberFormatException e) {
            // If number is Integer.MIN_VALUE, we'll end up here. The next line
            // handles this case, and causes any genuine format error to be
            // rethrown.
            String constant = negative ? ("-" + nm.substring(index))
                                       : nm.substring(index);
            result = Integer.valueOf(constant, radix);
        }
        return result;
    }

将 String 解码为 int,支持十进制、八进制、十六进制。

  1. 首先判断参数 nm 的符号
  2. 再判断参数 nm 的基底。是以 8 为基底的八进制,还是以 16 位基底的十六进制,还是以 10 位基底的十进制
  3. 然后对字符串进行截取,只保留纯数字部分,再调用 valueOf 方法进行处理并返回结果

valueOf(int i)

    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

如果 int 值在缓冲池的范围内(默认为-128~127,最大值可设置到 Integer.MAX_VALUE),则直接返回缓冲池中的 Integer 实例,否则创建一个新的 Integer 实例。在创建 Integer 实例时应优先使用此方法。

valueOf(String s) 和 valueOf(String s, int radix)

    public static Integer valueOf(String s) throws NumberFormatException {
        return Integer.valueOf(parseInt(s, 10));
    }
    
    public static Integer valueOf(String s, int radix) throws NumberFormatException {
        return Integer.valueOf(parseInt(s,radix));
    }

调用 parseInt 方法,然后对结果值调用 valueOf(int i) 方法,尝试从缓存中直接获取 Integer 对象。

parseInt

    public static int parseInt(String s) throws NumberFormatException {
        return parseInt(s,10);
    }
    
	//	 这个方法可以在 IntegerCache 初始化之前调用
	public static int parseInt(String s, int radix) throws NumberFormatException {
       
        if (s == null) {
            throw new NumberFormatException("null");
        }
		        
        if (radix < Character.MIN_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " less than Character.MIN_RADIX");
        }
                  
        if (radix > Character.MAX_RADIX) {
            throw new NumberFormatException("radix " + radix +
                                            " greater than Character.MAX_RADIX");
        }

        int result = 0;
        boolean negative = false;
        int i = 0, len = s.length();
        int limit = -Integer.MAX_VALUE;
        int multmin;
        int digit;

        if (len > 0) {
            char firstChar = s.charAt(0);
            if (firstChar < '0') { // Possible leading "+" or "-"
                if (firstChar == '-') {
                    negative = true;
                    limit = Integer.MIN_VALUE;
                } else if (firstChar != '+')
                    throw NumberFormatException.forInputString(s);

                if (len == 1) // Cannot have lone "+" or "-"
                    throw NumberFormatException.forInputString(s);
                i++;
            }
            multmin = limit / radix;
            while (i < len) {
                // 将字符转成不同基底的int类型
                digit = Character.digit(s.charAt(i++),radix);
                if (digit < 0) {
                    throw NumberFormatException.forInputString(s);
                }
                if (result < multmin) {
                    throw NumberFormatException.forInputString(s);
                }
                result *= radix;
                if (result < limit + digit) {
                    throw NumberFormatException.forInputString(s);
                }
                result -= digit;
            }
        } else {
            throw NumberFormatException.forInputString(s);
        }
        return negative ? result : -result;
    }

将数值类字符串转换成指定基底(默认为十进制)的有符号整数。

  1. 防御性编程。如果 字符串为 null 、为空串 和 基底不在合法范围,则抛出 NumberFormatException 异常
  2. 正负数处理。如果为负数,则除了第一个字符可以是 ‘-’ 外,其他字符必须全是数字。否则抛出同上的异常。
  3. Character.digit(char, int) 将字符转换为指定基底的 int 型数值,然后进行进制转换

进制转换的算法都是类似的。比如将 “129” 转换为十进制:

129 = 1 * 10^2 + 2 * 10^1 + 9 * 10^0 = (1 * 10 + 2* 10 + 9)

这里要注意的一点是,limit 是负数,也就是说在进制转换时是用负数来做运算的。这是因为 Integer 的最大负数值 Integer.MIN_VALUE 变为正数时会产生溢出。所以采用负数进行了一种等价运算。

parseUnsignedInt

public static int parseUnsignedInt(String s) throws NumberFormatException {
    return parseUnsignedInt(s, 10);
}

public static int parseUnsignedInt(String s, int radix)
    throws NumberFormatException {
    if (s == null)  {
        throw new NumberFormatException("null");
    }

    int len = s.length();
    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar == '-') {
            throw new
                NumberFormatException(String.format("Illegal leading minus sign " +
                                                    "on unsigned string %s.", s));
        } else {
            if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits
                (radix == 10 && len <= 9) ) { // Integer.MAX_VALUE in base 10 is 10 digits
                return parseInt(s, radix);
            } else {
                long ell = Long.parseLong(s, radix);
                if ((ell & 0xffff_ffff_0000_0000L) == 0) {
                    return (int) ell;
                } else {
                    throw new
                        NumberFormatException(String.format("String value %s exceeds " +
                                                            "range of unsigned int.", s));
                }
            }
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
}

1.8后新增的方法,和 parseInt 一样,将非负的数值字符串转换成无符号的整数。其数值范围为 0~65535。

  1. 如果字符串为 null 或第一个字符为 ‘-’,则抛出NumberFormatException异常
  2. 如果字符串长度小于5或是小于9的十进制,则直接调用内部的 parseInt 方法。小于5是因为int的最大值转换为最大进制(36)的数值后,其长度为6。
  3. 第二步不满足,表示数值字符串已经超出了范围,需要用长整型来处理,否则可能会溢出。先执行 Long.parseLong,然后判断结果的高八位是否为0,如果为0则表示结果在无符号整型的范围内,直接返回。否则抛出异常,提示超出范围。

总结

  • parseInt 方法的是 int,其他方法返回的是包装类 Integer
  • 调用链:getInteger(String nm) --> getInteger(nm, null);–>Integer.decode()
    –>Integer.valueOf()–>parseInt()
  • 从系统配置中取值,使用 getInteger

重写父类的xxxValue()

    public byte byteValue() {
        return (byte)value;
    }
    public short shortValue() {
        return (short)value;
    }
    public int intValue() {
        return value;
    }
    public long longValue() {
        return (long)value;
    }
    public float floatValue() {
        return (float)value;
    }
    public double doubleValue() {
        return (double)value;
    }

除 intValue() 方法外,其他都通过强制类型转换转换成了对应的基本类型。

比较 compare

有符号比较

    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }
    
    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

可以看到就是用自身的 value 和传入值比较大小。

无符号比较

    public static int compareUnsigned(int x, int y) {  
        return compare(x + MIN_VALUE, y + MIN_VALUE);
    }
    //	  System.out.println(Integer.compareUnsigned(-14, -25)); //输出1,前者大

无符号比较就是将 int 的二进制最高位不当作符号位来进行比较。

运算

求两者间的最大值 Max(int,int)

    public static int max(int a, int b) {
        return Math.max(a, b);
    }

求两者间的最小值 Min(int,int)

    public static int min(int a, int b) {
        return Math.min(a, b);
    }

求两者的商 divideUnsigned(int,int)

    public static int divideUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) / toUnsignedLong(divisor));
    }

求两者的余 remainderUnsigned(int,int)

    public static int remainderUnsigned(int dividend, int divisor) {
        // In lieu of tricky code, for now just use long arithmetic.
        return (int)(toUnsignedLong(dividend) % toUnsignedLong(divisor));
    }

求两者的和 sum(int,int)

    public static int sum(int a, int b) {
        return a + b;
    }

equals

    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

和 Byte 类似。

hashCode

    @Override
    public int hashCode() {
        return Integer.hashCode(value);
    }
    
    public static int hashCode(int value) {
        return value;
    }

和 Byte 一样,直接返回成员变量 value

highestOneBit(int)

    public static int highestOneBit(int i) {
        // HD, Figure 3-1
        i |= (i >>  1);
        i |= (i >>  2);
        i |= (i >>  4);
        i |= (i >>  8);
        i |= (i >> 16);
        return i - (i >>> 1);
    }

没看懂,写了个例子

        Integer value = Integer.valueOf(14);
        System.out.println(Integer.toBinaryString(value));	// 1110
        System.out.println(Integer.highestOneBit(14));		// 8=1000

该方法保留int类型从左边开始数第一个1,然后把其他位全置为0。

lowestOneBit(int)

    public static int lowestOneBit(int i) {
        // HD, Section 2-1
        return i & -i;
    }

highestOneBit 相反,该方法保留int类型从右边开始数第一个1,然后把其他位全置为0。

numberOfLeadingZeros(int i)

    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类型的二进制左边0的个数

        System.out.println(Integer.toBinaryString(14));	// 1110
        int result = Integer.numberOfLeadingZeros(14);	// 28 表示二进制形式的左边有28个0

numberOfTrailingZeros(int i)

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

该方法返回int类型的二进制右边0的个数

        System.out.println(Integer.toBinaryString(14));	// 1110
        int result = Integer.numberOfLeadingZeros(14);	// 1 表示二进制形式的右边有1个0

翻转 reverse

代码比较晦涩。通过各种移位、逻辑运算 、位运算,充分利用 CPU 的特性高效地实现了翻转

其他

剩下的方法比较简单:

  • 循环左移 rotateLeft
  • 循环右移 rotateRight
  • 返回符号位 signum(如果为负数,则返回 -1;如果为零,则返回 0;如果为正数,则返回 1)

阅读推荐

从JDK源码看二分思想:讲解 Integer类的 numberOfLeadingZeros 方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值