將一個整形數轉換成字符串形式

假如給你一個題目,將一個整型數轉換成它的字符串形式,你會怎麼做,你會這樣做,new Integer(432).toString(),或者Integer.toString(432),再或者Integer.toString(432,10)這幾個方法都能辦到,但是他們是怎麼實現的呢,假如讓你去實現你怎麼做呢,我們通常的做法是:

public static String convertIntToString(int i){
	int j = 0; //用來表示表示i中每一位上的數字
	int size = 0; //用來表示i的位數
	size = (i < 0) ? sizeOfInt(-i) + 1:sizeOfInt(i);
	char[] buf = new char[size];
		
	if(i < 0){
		i = -i;
		buf[0] = '-';
	}
		
	while(i != 0){
		j = i % 10;
		i = i / 10;
		buf[--size] = Digit[j];
	}
		
	return new String(buf);
}
	
public static int sizeOfInt(int x){
	int i = 0;
	while(x != 0){
		x /= 10;
		i++;
	}
	return i;
}
	
public static char[] Digit = {
	'0','1','2','3','4','5','6','7','8','9'
};

converIntToString()方法可以將任意的整形數轉換成它的字符串形勢,但是java庫函數中是怎麼實現的呢?在Integer類中的有個方法toString(int i)將整型轉換成字符串表示,這個實現方法對滲透了對性能的考慮,對實際情況的考慮,讓我們學習一下java源碼。

	/**
	*將i轉換成其字符串形式
	*/
    public static String toString(int i) {
		////如果i是int的最小值,直接返回一個常數,不用進行計算,
		//不知道爲什麼沒有對int的最大值進行優化,可能會在其他地方已經優化了,
        if (i == Integer.MIN_VALUE)  
            return "-2147483648";
        int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);  //利用size方法計算i的位數
        char[] buf = new char[size];
        getChars(i, size, buf);  //這一步纔將i的值轉換成字符數組,使用了getChars方法,這個方法也很與衆不同啊
        return new String(buf, true);
    }
	
	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;
    }
	
	/**
     * Places characters representing the integer i into the
     * character array buf. The characters are placed into
     * the buffer backwards starting with the least significant
     * digit at the specified index (exclusive), and working
     * backwards from there.
     *
     * Will fail if i == Integer.MIN_VALUE
     */
    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就執行這個循環,一次能產生兩個字符哦
        while (i >= 65536) {
            q = i / 100;
			// really: r = i - (q * 100); 
			//用移位操作比直接的乘法操作要快,以後咱們自己寫程序,能不能從運用大師們的這一招呢?
            r = i - ((q << 6) + (q << 5) + (q << 2));
            i = q;
			 //這兩個數組設計的比較精巧,
			 //DigitOne中根據數組下表能取出各位數的字符表示,
			 //DigitTens取出十位上數的字符表示
            buf [--charPos] = DigitOnes[r];
            buf [--charPos] = DigitTens[r];
        }

        // Fall thru to fast mode for smaller numbers
        // assert(i <= 65536, i);
        for (;;) {
            //這一步牛b吧完成的是i/10操作,>>>這個操作符的意思是向右移位之後用0填充最高位。
			//但是這一步還是沒有看懂到底是怎樣移位的,求高手賜教
			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',
        } ;
		
	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'
    };

通過閱讀java源碼,我們能從中學到這樣幾點:
 1.儘可能的用移位操作代替乘除法
 2.有時候查表操作比直接運算性能要好
 3.考慮問題要全面,不要寫一些教學用的代碼片段,要充分考慮問題的情況,
   比如這裏面就充分考慮了,整型數如果大於65536怎麼操作,小於65536又怎麼操作,

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章