今天,简单讲讲android里如何使用Integer类的toString函数。
这个其实很简单,就是将整数转成字符串。不过之前一直使用的是String.value()来进行转换的。后来在为网上查找资料,发现Integer类的toString函数的效率更高,所以在这里记录一下。
一.下面介绍一下Integer类----toString函数的作用
toString方法---- 生成整数的十进制字符串 返回一个表示制定整数的String对象,将该参数转换为有符号的十进制表形式,以字符串形式返回它,就好像将参数和基数10作为参数赋予toString(int,int),方法。
方法声明1
Public static String toSring(int i);
入口参数:i为表示要转换成字符串的整数;
返回值:十进制(基数10)参数的字符串表示形式,
二.String.valueOf(int i)方法和Integer.toString(int i)方法的效率比较
1、String.valueOf(int i)
2、Integer.toString(int i)
3、i+""; //i 为 int类型
三种方法效率排序为:
Integer.toString(int i) > String.valueOf(int i) > i+"";
代码测试:
public static void main(String[] args) { int[] intArr = new int[1000000]; String[] strArr1 = new String[1000000];//为了公平分别定义三个数组 String[] strArr2 = new String[1000000]; String[] strArr3 = new String[1000000]; //赋值 Long t1 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ intArr[i]=i+1; } Long t2 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ strArr1[i] = String.valueOf(intArr[i]); } Long t3 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ strArr2[i] = Integer.toString(intArr[i]); } Long t4 = System.currentTimeMillis(); for(int i=0;i<1000000;i++){ strArr3[i] = intArr[i]+""; } Long t5 = System.currentTimeMillis(); System.out.println("t1 = "+t1); System.out.println("t2 = "+t2); System.out.println("t3 = "+t3); System.out.println("t4 = "+t4); System.out.println("t5 = "+t5); System.out.println("赋值:"+(t2-t1)); System.out.println("String.valueOf(i):"+(t3-t2)); System.out.println("Integer.toString(i):"+(t4-t3)); System.out.println("i+/"/":"+(t5-t4)); }
我的测试结果为:
t1 = 1298798872078
t2 = 1298798872093
t3 = 1298798872656
t4 = 1298798873000
t5 = 1298798873671
赋值:15
String.valueOf(i):563
Integer.toString(i):344
i+"":671
简单讲讲,大家可以会想知道为什么Integer.toString(int i)方法比String.valueOf(int i)方法效率高。可以看看android的源码:
public static String valueOf(int i) { return Integer.toString(i); }我们可以看到,String.valueOf(int i)其实是调用了Integer.toString(int i)方法的。
3.从源码理解Integer类的toString方法
下面就深入看看Integer类的toString方法是如何实现的。还是直接上源码。
public String toString() { return toString(value); } //------------------------------ public static String toString(int i) { if (i == Integer.MIN_VALUE) return "-2147483648"; //如果是最小值直接返回其字符串因为Integer.MIN_VALUE=-2147483648 ,这样可以节省下面计算时间 //① int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i); //获取整数值的长度10进制 char[] buf = new char[size]; //② getChars(i, size, buf); //得到整数中的每一个字符 //③ return new String(buf, true); //返回字符串值 }
上面的代码做几点说明:
①如果Integer的value值正好是 Integer.MIN_VALUE 直接返回 “-2147483648” 节省时间。
②得到integer值的十进制的长度,如果负数先求出绝对值的长度,然后再长度加1,因为负数的符号位占一位。
③得到integer的value值的每一个字符。
④得到的字符新建字符串返回。
下面看看 stringSize方法是怎样实现的:
static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) return i+1; //看看x到底是几位数 } //---------------------------------- final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE };
上面的 stringSize 非常的巧妙的来整数的长度,首先定义了一个数组这个数组中分别存放了一位十进制的最大值,二位十进制的最大值,依次到 Integer.MAX_VALUE为止,因为integer的最大值为 Integer.MAX_VALUE,也就是说integer的最大长度为10位。注意:
①stringSize(int x) 中的参数x 必须是正整数。
下面用一个实例看看stringSize(int x)方法。
public class IntegerDemo { public static void main(String[] args) { int x=199; int max=Integer.MAX_VALUE; int out_max=Integer.MAX_VALUE+1; System.out.println(stringSize(x)); System.out.println("-------------------------"); System.out.println(stringSize(max)); System.out.println("-------------------------"); System.out.println(stringSize(out_max)); } final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE }; static int stringSize(int x) { for (int i=0; ; i++) if (x <= sizeTable[i]) return i+1; } } //输出 /* 3 ------------------------- 10 ------------------------- 1 */
上面的199小于999所以位数为3,而 out_max的值因为超过了 Integer.MAX_VALUE是个负数,得到的长度为1,因此求负数的长度时必须将其转化为正数来求,而且求出的长度还要加上一位来放‘ - ’。得到integer的value值的长度后使用 getChars 方法来得到value的每一位上的字符。下面看看这个getChars方法。
static void getChars(int i, int index, char[] buf) { int q, r; int charPos = index; char sign = 0; if (i < 0) { sign = '-'; i = -i; } // 当i >= 65536的时候每一次获取两位的char值。 while (i >= 65536) { q = i / 100; // really: r = i - (q * 100); r = i - ((q << 6) + (q << 5) + (q << 2)); //使用移位操作快速计算出q*100,2^6+2^5+2^2=64+32+4=100. i = q; buf [--charPos] = DigitOnes[r]; buf [--charPos] = DigitTens[r]; } // 当 i <= 65536的时候每次只获取一位的char值 // assert(i <= 65536, i); for (;;) { q = (i * 52429) >>> (16+3); //q/10,2^19=524288, (double)52429/(1<<19)=0.10000038146972656 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 [] 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', } ; //-------------------------------------- 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', } ;
getChars方法也是十分的巧妙
①在 i >= 65536 的时候每次能够求出2位的char 值,求2位的char值时利用了两个数组 DigitOnes 和 DigitTens 就是在这两个数组的帮助下才能一次求出2位的char值下面就简单的说一下怎样利用这两个数组来分别求出个位和十位上的值的,假如现在得到两位数是 65,个位上是 5 要得到个位上的5,这时候不管十位是多少个位上一定是5,所以数组DigitOnes的 05,15,25,35,45,55,65,75,85,95位置上都是 5,这样不管是25,还是35 都能得到个位上的5。在来看看如何得到十位上的数,还是65,十位是6,所以DigitTens 的60,61,62,63,64,……69 位置上都是6。
② q = (i * 52429) >>> (16+3);这段代码其实就是q=i/10 ,其中 (double)52429/(1<<19)=0.10000038146972656也就是在int型的时候计算一个数的十分之1的精度是够的,可以看出jdk开发者的这种优化意识是非常强的。
③(q << 6) + (q << 5) + (q << 2) 这段等价于q*100,因为 q*2^6+q*2^5+q*2^2=q*(64+32+4)=100q.这里为什么不直接使用q*100,而要使用位移操作,因为其实q*100底层还是要进行位移操作的,直接使用位移操作效率更高,这也给我们编程带来启示。能够优化的时候一定要优化。
简单讲讲,当传入整数是Integer.MIN_VALUE,直接返回字符串“-2147483648”。其他整数时,先调用stringSize(int x)获取整数的长度,这里主要一点,负数的长度会加1.(因为负号)然后新建一个char[] 数组,调用getChars(i, size, buf);将整数转成字符数组,具体怎么转换,代码里很清楚。最后调用new String(buf, true);将字符数组变成String返回到调用代码。
android Integer类的toString函数的使用就讲完了。
就这么简单