如果让您亲自动手来来写一个Integer中的toString()方法和parseInt()方法,您会怎么写?
请您先动手写toString()方法。
我对于toString()的思路:
1.首先需要得到这个Integer数值的位数,所以肯定有一个getIntegerSize()的private方法
2.然后要把这个Integer数值转化为一个字符数组,所以也要有一个getChars()的private方法
3.最后只要把这个字符数组转化为字符串返回即可
在编写完我们的代码,再确定对于现在自己的实力,已经没有再做优化的可能之后,再来看Integer中的toString()来领教一下高手的代码是怎么写的。
下面是这个过程中最重要的一步:将数值转成字符数组;
其中用使用来三个表(DigitOnes、DigitTens、digits)作为表驱动法(在代码大全上看到过,但还没用过:P)的快速索引来加快代码的执行效率。
[java] view plaincopyprint?
01./**
02. * @param i 被转十进制数
03. * @param index 这个十进制数的总位数
04. * @param buf 用来存储转化后的结果
05. */
06.static void getChars(int i, int index, char[] buf) {
07. int q, r;
08. int charPos = index;
09. char sign = 0;
10.
11. if (i < 0) {
12. sign = '-';
13. i = -i;
14. }
15.
16. // Generate two digits per iteration
17. while ( i >= 65536 ) {
18. q = i / 100;
19. r = i - ( ( q 《 6 ) + ( q 《 5 ) + ( q 《 2 ) ); // 高效实现 r = i - ( q * 100 );
20. i = q;
21. buf [ --charPos ] = DigitOnes[ r ];
22. buf [ --charPos ] = DigitTens[ r ];
23. }
24.
25. // Fall thru to fast mode for smaller numbers
26. // assert( i <= 65536, i );
27. for (;;) {
28. q = ( i * 52429 ) >>> (16+3 ); //实现 q = i / 10(其中使用整数乘法后再移位来代替浮点数的乘法(q * 0.1),但对于现在的CPU来说不 //知是否还是整数乘法较快?)
29. r = i - ( ( q 《 3 ) + ( q 《 1 ) ); //高效实现 r = i - ( q * 10 ) …
30. buf [ --charPos ] = digits [ r ];
31. i = q;
32. if ( i == 0 ) break;
33. }
34. if ( sign != 0 ) {
35. buf [ --charPos ] = sign;
36. }
37.}
/**
* @param i 被转十进制数
* @param index 这个十进制数的总位数
* @param buf 用来存储转化后的结果
*/
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
while ( i >= 65536 ) {
q = i / 100;
r = i - ( ( q 《 6 ) + ( q 《 5 ) + ( q 《 2 ) ); // 高效实现 r = i - ( q * 100 );
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 ); //实现 q = i / 10(其中使用整数乘法后再移位来代替浮点数的乘法(q * 0.1),但对于现在的CPU来说不 //知是否还是整数乘法较快?)
[java] view plaincopyprint?
01./**
02. * All possible chars for representing a number as a String
03. */
04. final static char[] digits = {
05. '0' , '1' , '2' , '3' , '4' , '5' ,
06. '6' , '7' , '8' , '9' , 'a' , 'b' ,
07. 'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
08. 'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
09. 'o' , 'p' , 'q' , 'r' , 's' , 't' ,
10. 'u' , 'v' , 'w' , 'x' , 'y' , 'z'
11. };
12.
13. /**
14. * 传入一个二位十进制数,返回其十位上的数值
15. */
16. final static char [] DigitTens = {
17. '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
18. '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
19. '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
20. '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
21. '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
22. '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
23. '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
24. '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
25. '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
26. '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
27. } ;
28.
29. /**
30. * 传入一个二位十进制数,返回其个位上的数值
31. */
32. final static char [] DigitOnes = {
33. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
34. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
35. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
36. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
37. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
38. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
39. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
40. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
41. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
42. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
43. } ;
/**
* All possible chars for representing a number as a String
*/
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'
};
/**
* 传入一个二位十进制数,返回其十位上的数值
*/
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',
} ;
虽然API的实现耗费了不少空间,但是其效率要比我写的要快多了(- -!!)。如果大家不明白上面的位移操作符可以看:Java中的位移运算符
对于得到一个整数数值的位数,我采用了的是不断取余操作(不知道多少兄弟和我想到一块儿去了,^ ^.但是取余操作效率相比之下要慢上不少)。那么API是如何快速得到一个整数数值的位数的呢?其中又采用了表驱动法来取代if-else: