Java Integer常用方法总结

Java Integer常用方法总结

主要是参考了这篇博客


1.主要属性

 @Native public static final int   MIN_VALUE = 0x80000000; 
 // 值为 -2^31 的常量,它表示 int 类型能够表示的最小值。
@Native public static final int   MAX_VALUE = 0x7fffffff; 
 // 值为 2^31-1 的常量,它表示 int 类型能够表示的最大值。
@Native public static final int SIZE = 32;  
// 用来以二进制补码形式表示 int 值的比特位数。
public static final int BYTES = SIZE / Byte.SIZE; 
// 返回int值所占的字节数。
public static final Class<Integer>  TYPE = (Class<Integer>) Class.getPrimitiveClass("int"); 
// 表示基本数据类型 int 的 Class 实例。
private final int value;//包装了一个基本类型int的值

2.构造方法

// 1、构造一个新分配的 Integer 对象,它表示指定的 int 值。
public Integer(int value) {
        this.value = value;
}
// 2、构造一个新分配的 Integer 对象,它表示 String 参数所指定 int 值。
// 要注意的是字符串不能包含非数字字符,否则会抛出NumberFormatException
public Integer(String s) throws NumberFormatException {
        this.value = parseInt(s, 10);
}
//3、除此之外,还可以给Integer对象直接赋值,如:
Integer a = 10;//涉及到自动装箱

3、bitCount方法
返回指定 int 值的二进制补码表示形式的是1的位数量,譬如Integer.bitCount(15),返回值为4。

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

4、xxxValue方法

// 以 byte 类型返回该 Integer 的值
public byte byteValue() {
        return (byte)value;
}
// 以 short 类型返回该 Integer 的值
public short shortValue() {
        return (short)value;
}
// 以 int 类型返回该 Integer 的值
public int intValue() {
        return value;
}
// 以 long 类型返回该 Integer 的值
public long longValue() {
        return (long)value;
}
// 以 float 类型返回该 Integer 的值
public float floatValue() {
        return (float)value;
}
// 以 double 类型返回该 Integer 的值
public double doubleValue() {
        return (double)value;
}

5、比较方法

// 比较x和y的值,当x大于y时返回1,当x等于y时返回0,否则返回-1
public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
// 在数值上比较两个Integer对象
public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
}

6、equals方法
比较此对象与指定对象是否相等 。首先判断指定对象是否为Integer类型,在判断两者 int 的值是否相等。

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

7、hashCode方法
返回此对象的哈希码 。

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

8、int—>String、String—>int方法
int—>String

static String toString(int i);
// Integer类中的静态方法,可以返回一个表示指定整数的 String 对象。
//其他方法:String类中有valueOf方法; 和""(空字符串)进行拼接。

String—>int

static int parseInt(String s) 
//将字符串参数作为有符号的十进制整数进行解析,返回一个和字面值一样的int型数据。
static Integer valueOf(String s) 
//返回保存指定的 String 值的 Integer 对象,然后调用intValue方法,获取int值。

9、进制转换方法

static String toBinaryString(int i) 
//以二进制(基数 2)无符号整数形式返回一个整数参数的字符串表示形式
static String toHexString(int i) 
//以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式
static String toOctalString(int i) 
//以八进制(基数 8)无符号整数形式返回一个整数参数的字符串表示形式

10、其他
1)装箱和拆箱

Integer i = 100;  //自动装箱
i += 200;            //自动拆箱
int ii = i.intValue(); //手动拆箱
Integer i1 = Integer.valueOf(100);//手动装箱

2)int和Integer
Integer是int的包装类,int则是java的一种基本数据类型;Integer变量必须实例化后才能使用,而int变量不需要;Integer实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象(堆中);而int则是直接存储数据值 (栈中);Integer的默认值是null,int的默认值是0。
由于Integer变量实际上是一个Integer对象的引用,所以两个通过new生成的Integer变量永远是不相等的(因为new生成的是两个对象,其内存地址不同)。

Integer i = new Integer(100);
Integer j = new Integer(100);
System.out.print(i == j); //false

Integer变量和int变量比较时,只要两个变量的值是相等的,则结果为true(因为包装类Integer和基本数据类型int比较时,java会自动拆箱装为int,然后进行比较,实际上就变为两个int变量的比较)。。

Integer i = new Integer(100);
int j = 100;
System.out.print(i == j); //true

非new生成的Integer变量和new Integer()生成的变量比较时,结果为false。(因为非new生成的Integer变量指向的是java常量池【对于Integer类来说是IntegerCache类】中的对象【对于 -128~127 来说】,而new Integer()生成的变量指向堆中新建的对象,两者在内存中的地址不同)。

Integer i = new Integer(100);
Integer j = 100;
System.out.print(i == j); //false

对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间 -128到127 之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false。

Integer i = 100;
Integer j = 100;
System.out.print(i == j); //true

Integer i = 128;
Integer j = 128;
System.out.print(i == j); //false

关于自动装箱和自动拆箱,反编译之后:把装箱转换为Integer.valueOf(),把拆箱转换为Integer.intValue()
Integer.valueOf()方法:

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

IntegerCache类的源码:
可以看出Integer 的缓存范围默认是-128到127。当然缓存上限值也是可以根据需要调整的,JVM提供了参数设置-XX:AutoBoxCacheMax=,这也就解释了上述代码中i1 == i2 结果为true,而i3 == i4false的根本原因,即在-128到127(包含)之间的数值都是IntegerCache.cache[] 数组中的同一个Integer对象。
举一反三,这种缓存机制并不只有Integer才有,同样存在于其他一些包装类:

Boolean,缓存了true/false实例
Byte,数值全部被缓存
Short,缓存了-128127之间到数值
Character,缓存范围'\u0000''\u007f'0127)
Long,缓存了-128127之间的数值
/**
 * Cache to support the object identity semantics of autoboxing for values between
 * -128 and 127 (inclusive) as required by JLS.
 *
 * The cache is initialized on first usage.  The size of the cache
 * may be controlled by the {@code -XX:AutoBoxCacheMax=} option.
 * During VM initialization, java.lang.Integer.IntegerCache.high property
 * may be set and saved in the private system properties in the
 * sun.misc.VM class.
 */
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() {}
}

3)绝对值问题
Integer的界限范围与int类型是一致的,都是 0x7fffffff~0x80000000 。 这两个范围大家经常用,一般不会出现问题。但是,由于补码表示负数的关系,正数总是比负数少一个。作为边界值,这经常会导致问题。例如下面的Math类中代码:

public static int abs(int a) {
        return (a < 0) ? -a : a;
}

这里返回结果不全是正数,输入Integer.MIN_VALUE的结果还是Integer.MIN_VALUE,因为没有相应的补码与之对应。所以在使用绝对值的时候还是要小心的,要考虑是否会出现一个Integer.MIN_VALUE的输入,如果有可能,那就需要更大范围的类型(Long)来表示或者单独对它进行处理。Math提供的abs方法并没有考虑这个问题。
4)进制转换
下面的方法是将形参i转成radix进制的数 :

// 代表数字的所有可能的字符
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'
};

public static String toString(int i, int radix) {
        // 如果小于2进制或大于36进制,当成10进制处理
        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
            radix = 10;

        /* Use the faster version */
        // 10进制数,直接使用更快的版本
        if (radix == 10) {
            return toString(i);
        }

        // Integer最多占用33位,数字32位,符号1位
        char buf[] = new char[33];
        // 判断是否为负数,后面i被当成负数来统一处理(负数范围比正数大,不需要额外处理Integer.MIN_VALUE的问题)
        boolean negative = (i < 0);
        // buf最末尾的索引,从32开始
        int charPos = 32;

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

        // i%radix的余数的绝对值放到buf当前尾部(charPos)位置
        while (i <= -radix) {
            buf[charPos--] = digits[-(i % radix)];
            i = i / radix;
        }
        buf[charPos] = digits[-i];

        if (negative) {
            buf[--charPos] = '-';
        }
        
        // 返回字符串,从buf的charPos位置开始截取,长度33-charPos,正好是最后一个位置,索引下标为32
        return new String(buf, charPos, (33 - charPos));
}

快速的十进制转换方法:

public static String toString(int i) {
        // 如果是Integer的最小值,直接返回字符串"-2147483648"
        if (i == Integer.MIN_VALUE)
            return "-2147483648";
        
        // 计算形参i的位数,负数的话,size要比数字本身多1,用来存储负号(-)
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
        char[] buf = new char[size];
        getChars(i, size, buf);
        return new String(buf, true);
}

static void getChars(int i, int index, char[] buf) {
        int q, r; // r为余数,就是每次被插入到buf的数
        int charPos = index;
        char sign = 0;

        if (i < 0) {
            sign = '-';
            i = -i;
        }

        // Generate two digits per iteration
        // 每次迭代向buf插入2个数字,即i的最后两位,目的应该是加快迭代速度
        while (i >= 65536) {
            q = i / 100;
            // really: r = i - (q * 100);
            // i - q * 100 得到的r就是i的末尾2位数,本质是i%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 (;;) {
            // 这里本质就是i/10
            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;
        }
}

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

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

(1) ALU执行乘法和移位运算的速度快过除法的运算速度。
(2)52429,看到这个数字,联想到524288也就是2^19。q = (i * 52429) >>> (16+3);实际上这应该是除10的方法,即:
i*52429>>>(19,实际上可以这么写:i*52429/524288,而52429/524288≈0.1000003
而我们知道>>>的速度是快于除法的,所以只是java的优化。
那么为什么是2^19呢?稍微列式便能得出,这么计算的话:

103/10240.1006
205/20480.100098
……
52429/5242880.1000003

发现2^19精度最高啊。
那么选2^20行吗?
65536=2^16,52429<65536,所以i * 52429 < 2^32,不会溢出 。那么选2^20会溢出。

你可能感兴趣的:(Java)