漲見識!Java String轉int還有這種寫法
先看再點贊,給自己一點思考的時間,微信搜尋【沉默王二】關注這個有顏值卻假裝靠才華苟且的程式設計師。
本文 GitHub github.com/itwanger 已收錄,裡面還有我精心為你準備的一線大廠面試題。
之前我寫了一篇《老師,你確定Java註釋不會被執行嗎》,結果文章在知乎小火了一把,將近 10 萬人閱讀。有愛裝逼的同行批評說,標題誇大了; 同時,也有很多初學者表示,漲見識了,之前從來不知道這個知識點,這下學到了。
必須得承認一點,我寫的大多數技術文章都是針對初學者的,因為我覺得他們最需要幫助,這也是我一直堅持分享的初衷。
我也不喜歡寫那些高深的文章,費時間耗精力,受眾也小。就拿我們學過的古詩來說吧,“鵝鵝鵝,曲項向天歌”,“一去二三裡,煙村四五家”,我就覺得挺好的。沒必要都去搞陽春白雪,最後搞得曲高和寡,對吧?
那這次來分享一個新的知識點,我敢賭一包衛龍辣條(打錢來),很多同學不一定知道。
在 Java 中,String(字串) 和 int(整形) 是兩種不同的資料型別,字串可以把許多字串起來,整形嘛——就是整形了。
(同學們可能會疑惑,這個知識點我能不知道,別蒙我好不好?繼續往下看唄。吃大餐之前,還能不來點小吃或者冷盤?)
有時候,字串可以單純包含一些數字,比如說“123”。大家應該都見過,當一些操作需要你輸入手機驗證碼的時候,大部分要求輸入的都是 6 位或者 4 位的隨機數字,它們傳遞到伺服器端的時候,最初的形式都是字串型別的,然後可能再轉成整形做一些處理。
對於 Java 來說,不能直接通過“+”操作符來使兩個字串型別的數字相加,來看下面的例子。
Stringa="100";
Stringb="50";
Stringc=a+b;
System.out.println(c);
程式輸出的結果是 10050,而不是 150。對於字串來說,“+”操作符是用來串聯的,而不是用來相加的。
(同學們可能又要催了,這個知識點我也知道啊!馬上馬上,重點馬上就來。)
那就有必要先把字串轉成整形再來做運算了,常見的做法有兩種:
第一種,使用 Integer.valueOf()
,它將返回一個包裝器型別 Integer,當然可以通過自動拆箱的方式將其轉成 int 型別。
Stringa="100";
Stringb="50";
intA=Integer.valueOf(a);
intB=Integer.valueOf(b);
int c=A+B;
System.out.println(c);
程式輸出結果如下所示:
150
第二種,使用 Integer.parseInt()
,它將返回一個基本資料型別 int。
Stringa="100";
Stringb="50";
intA=Integer.parseInt(a);
intB=Integer.parseInt(b);
intc=A+B;
System.out.println(c);
程式輸出結果如下所示:
150
這兩種方式,優先推薦第二種,因為不涉及到自動拆箱,效能更佳。
(同學們可能急不可耐了,就這?好了,現在重點真的來了)
那除了上面這兩種方式,同學們還能想到第三種嗎?把字串轉成整形。是不是突然感覺腦袋裡有點空?
空就對了,本篇文章最漲見識的時候,它來了!步履蹣跚地來了!
/**
*@author沉默王二,一枚有趣的程式設計師
*/
publicclassString2IntDemo{
publicstaticvoidmain(String[]args){
Stringa="100";
Stringb="50";
intA=string2int(a);
intB=string2int(b);
intc=A+B;
System.out.println(c);
}
publicstaticintstring2int(Strings){
intnum=0;
intpos=1;
for(inti=s.length()-1;i>=0;i--){
num+=(s.charAt(i)-'0')*pos;
pos*=10;
}
returnnum;
}
}
這段程式輸出的結果同樣是 150。那眼睛雪亮的同學可能就發現了,string2int()
方法到底是個什麼樣的神奇方法,還有把字串轉成整形的功效?
首先,必須得普及一點常識,同學們需要對 ASCII 碼有一點了解,就是所有的字元都有識別它們的程式碼——這程式碼就是 ASCII 碼。
基於這一點,所有數字型的字元減去字元‘0’,將會得到該字元的絕對值,是一個整數。
Strings="520";
System.out.println(s.charAt(2)-'0');
System.out.println(s.charAt(1)-'0');
System.out.println(s.charAt(0)-'0');
輸出結果如下所示:
0
2
5
字串“520”的長度為 3,也就是說,下標為 2 的位置是字元‘0’——數字 520 的個位數;下標為 1 的位置是字元‘2’——數字 520 的十位數;下標為 0 的位置是字元‘5’——數字 520 的百位數。
那有些機靈點的同學可能就想到了,通過一個 for 迴圈,遍歷一下字串,然後計算出當前位置上的整數值,個位數乘以 1,十位數乘以 10,百位數乘以 100,然後再加起來,就是字串對應的整數值了。
沒錯,沒錯,string2int()
方法就是這麼做的,如果引數是字串“520”,那返回的結果就是整形 520;如果引數是字串“100”,那返回的結果就是整形 100;如果引數是字串“50”,那返回的結果就是整形 50。
如果你是一名有追求的程式設計師,那麼對於 Integer.valueOf()
和 Integer.parseInt()
都不會太滿意,因為這只是拿別人的輪子來用。而自定義方法 string2int()
就屬於從頭到尾的造輪子了。一想到這,是不是感覺自己開始變牛逼了?
其實,如果你肯扒拉原始碼的話,就會恍然大悟。
先來看 Integer.valueOf()
方法:
publicstaticIntegervalueOf(Strings)throwsNumberFormatException{
returnInteger.valueOf(parseInt(s,10));
}
內部呼叫的其實就是 int parseInt(String s, int radix)
方法。
再來看 Integer.parseInt()
方法:
publicstaticintparseInt(Strings)throwsNumberFormatException{
returnparseInt(s,10);
}
內部呼叫的也是 int parseInt(String s, int radix)
方法,基數 radix 引數都是 10——同學們是不是猜到了什麼?
對,你猜的八九不離十,再來看一下 int parseInt(String s, int radix)
方法的原始碼:
publicstaticintparseInt(Strings,intradix)
throwsNumberFormatException
{
/*
*WARNING:ThismethodmaybeinvokedearlyduringVMinitialization
*beforeIntegerCacheisinitialized.Caremustbetakentonotuse
*thevalueOfmethod.
*/
if(s==null){
thrownewNumberFormatException("null");
}
if(radix<Character.MIN_RADIX){
thrownewNumberFormatException("radix"+radix+
"lessthanCharacter.MIN_RADIX");
}
if(radix>Character.MAX_RADIX){
thrownewNumberFormatException("radix"+radix+
"greaterthanCharacter.MAX_RADIX");
}
booleannegative=false;
inti=0,len=s.length();
intlimit=-Integer.MAX_VALUE;
if(len>0){
charfirstChar=s.charAt(0);
if(firstChar<'0'){//Possibleleading"+"or"-"
if(firstChar=='-'){
negative=true;
limit=Integer.MIN_VALUE;
}elseif(firstChar!='+'){
throwNumberFormatException.forInputString(s,radix);
}
if(len==1){//Cannothavelone"+"or"-"
throwNumberFormatException.forInputString(s,radix);
}
i++;
}
intmultmin=limit/radix;
intresult=0;
while(i<len){
//AccumulatingnegativelyavoidssurprisesnearMAX_VALUE
intdigit=Character.digit(s.charAt(i++),radix);
if(digit<0||result<multmin){
throwNumberFormatException.forInputString(s,radix);
}
result*=radix;
if(result<limit+digit){
throwNumberFormatException.forInputString(s,radix);
}
result-=digit;
}
returnnegative?result:-result;
}else{
throwNumberFormatException.forInputString(s,radix);
}
}
1)parseInt()
方法判斷了 null 的情況,認為格式不正確。
2)然後判斷了基數 radix 的情況,不能小於 2,不能大於 36。
3)if (len > 0)
判斷了字串長度的情況,如果為空“”,也認為格式不正確。
4)再然後判斷首個字元 s.charAt(0)
,如果是負號“-”則認為當前字串是一個負數;如果不是正號“+”,則認為格式不正確;如果只有一個負號或者正號,也認為格式不正確。
總之,就是比我們的自定義方法 string2int()
更嚴謹。
5)使用 while 迴圈,配合更專業的 Character.digit(s.charAt(i++), radix)
計算出每個位置上字元對應的數值,然後和基數 radix 進行相乘後使用累減的方式計算出最後的數值。
和 string2int()
有點不同,但整體上思路是一致的。
我們也可以對 string2int()
方法再完善一下,使其滿足負數的情況:
publicclassS2IDemo{
publicstaticvoidmain(String[]args){
Stringa="-100";
Stringb="50";
intA=string2int(a);
intB=string2int(b);
intc=A+B;
System.out.println(c);
}
publicstaticintstring2int(Strings){
booleannegative=false;
charfirstChar=s.charAt(0);
if(firstChar=='-'){
negative=true;
s=s.substring(1);
}
intnum=0;
intpos=1;
for(inti=s.length()-1;i>=0;i--){
num+=(s.charAt(i)-'0')*pos;
pos*=10;
}
returnnegative?-num:num;
}
}
當首個字元為負號‘-’的話,結果就返回負數,並且把原來的字串擷取掉第一位。其他不變,這時候,當 a 為“-100”,b 為“50”的時候,a + b 的結果就是 -50。
我就問一句,造輪子的感覺是不是很爽?反正我已經爽過了。
我是沉默王二,一枚有顏值卻假裝靠才華苟且的程式設計師。關注即可提升學習效率,別忘了三連啊,點贊、收藏、留言,我不挑,奧利給