優(yōu)雅編程之這樣考慮字符性能,你就“正?!绷耍ǘ?/h2>

開心一笑

【吃過晚飯?jiān)诳蛷d看報(bào)紙,問老婆:你洗碗了嗎? 老婆嚴(yán)肅的說:老公,你應(yīng)該這樣問,寶貝,我去幫你洗碗吧!然后我再說,老公,已經(jīng)洗好了。這樣顯著多好…… 于是,老公:寶貝,我去幫你洗碗吧!老婆:恩,去吧?!?/p>

提出問題

項(xiàng)目中字符串操作應(yīng)該注意的一些性能問題???

解決問題

勵(lì)志圖片

以下來自《Java程序性能優(yōu)化》這本書中的一點(diǎn)總結(jié),以及自己的想法,每篇文章都很短,不太喜歡寫太多,一步一步慢慢學(xué)就可以了:

String類的基本實(shí)現(xiàn):char數(shù)組,offset偏移量和String的count長(zhǎng)度

對(duì)String優(yōu)化主要表現(xiàn)在3個(gè)方面,同時(shí)也是String對(duì)象的3個(gè)特點(diǎn):

  • 不變性:String對(duì)象一旦生成,則不能再對(duì)它進(jìn)行改變。
  • 針對(duì)常量池的優(yōu)化。
  • 類的final定義。

例一:

@Test
public void testString(){
    String boy = "boy";
    String girl = "girl";
    String girl2 = "girl";
    String girl3 = new String("girl");
    System.out.println(boy == girl);//false
    System.out.println(girl == girl2);//true
    System.out.println(girl == girl3);//false
    System.out.println(girl == girl3.intern());//true

}
引用Java程序性能優(yōu)化圖片

subString內(nèi)存泄露問題

具體可以看高手文章:

http://www.cnblogs.com/techyc/p/3324021.html

在jdk6中,substring還是指向原來的字符串,可以用 new String(str.substring())避免內(nèi)存泄露,
在jdk7中,沒有這個(gè)問題

字符串分割和查找

使用效率更高的StringTokenizer類分割字符

例二:

@Test
public void testString(){

    String originalStr = null;
    StringBuffer sb = new StringBuffer();
    for(int i=0;i<10000;i++){
        sb.append("ay");
        sb.append(";");
    }
    originalStr = sb.toString();

    long startTime = System.currentTimeMillis();
    for(int i=0;i<10000;i++){
        //在這里分割10000次
        originalStr.split(";");
    }
    System.out.println(System.currentTimeMillis() - startTime);

}

結(jié)果花費(fèi):14920ms(我電腦比較 lan )

性能改造:

@Test
public void testString(){
    String originalStr = null;
    StringBuffer sb = new StringBuffer();
    for(int i=0;i<10000;i++){
        sb.append("ay");
        sb.append(";");
    }
    originalStr = sb.toString();
    long startTime = System.currentTimeMillis();

    StringTokenizer tokenizer = new StringTokenizer(originalStr,";");
    for(int i=0;i<10000;i++){
        while (tokenizer.hasMoreTokens()){
            tokenizer.nextToken();
        }
    }
    System.out.println(System.currentTimeMillis() - startTime);
}

結(jié)果花費(fèi):8ms(我電腦比較 lan ) 這不是一個(gè)等級(jí)的啊!get起來

高效率的charAt()方法

charAt()效率比startsWith()或者endsWith效率高,對(duì)于判斷單個(gè)字符開頭的還可以,對(duì)于多個(gè)的話,我測(cè)試下,效率并沒有高很多。

例三:

@Test
public void testString3(){

    String loveStr = "Love you!!!";
    long startTime = System.currentTimeMillis();
    //執(zhí)行100萬次
    for(int i=0;i<1000000;i++){
        //判斷是否以L開頭
        if(loveStr.charAt(0) == 'L'
                ){
        }
    }
    System.out.println(System.currentTimeMillis() - startTime);
}

結(jié)果花費(fèi):20ms

@Test
public void testString4(){

    String loveStr = "Love you!!!";
    long startTime = System.currentTimeMillis();
    //執(zhí)行100萬次
    for(int i=0;i<1000000;i++){
        //判斷是否以L開頭
        if(loveStr.startsWith("L")){
        }
    }
    System.out.println(System.currentTimeMillis() - startTime);
}

結(jié)果花費(fèi):27ms

StringBuffer和StringBuilder

String對(duì)象是不可變對(duì)象,因此在需要對(duì)字符串進(jìn)行修改操作時(shí),如字符串連接,替換,String對(duì)象總是會(huì)生成新的對(duì)象,所以其性能相對(duì)較差。

例四:

String love = "999玫瑰" + "999電話" + "999晚安" + "999早安";

StringBuilder result = new StringBuilder();
result.append("999玫瑰");
result.append("999電話");
result.append("999晚安");
result.append("999早安");

因?yàn)閖ava虛擬機(jī)對(duì)String拼接進(jìn)行性能的優(yōu)化。將多個(gè)連接操作的字符串,在編譯時(shí)合成一個(gè)單獨(dú)的長(zhǎng)字符串。所以上面二者效率差不多

雖然二者的性能差不多,但是作者還是建議在代碼的實(shí)現(xiàn)中盡量地使用StringBuilder或者StringBuffer,來提升程序性能,而不是依靠編譯器對(duì)程序進(jìn)行優(yōu)化。

例五:

// 1
for(int i=0;i<10000;i++){
    str = str + i;
}

//編譯器會(huì)把上面代碼編譯成以下代碼,但是每次會(huì)新建一個(gè) StringBuilder對(duì)象,效率自然就低了
for(int i=0;i<10000;i++){
    str = (new StringBuilder(String.valueOf(str))).append(i).toString();
}

// 2
for(int i=0;i<10000;i++){
    result = result.concat(String.valueOf(i));
}

// 3
StringBuilder sb = new StringBuilder();
for(int i=0;i<10000;i++){
    sb.append(i);

` }

上面的三個(gè)方法中效率(由低到高):

1 < 2 < 3

雖然java虛擬機(jī)會(huì)String的加法操作進(jìn)行優(yōu)化,但是編譯器還是不夠聰明。

StringBuffer和StringBuilder的選擇

StringBuffer和StringBuilder是一對(duì)孿生兄弟。

StringBuilder的效率 > StringBuffer的效率

StringBuilder是非線程安全的。StringBuffer是線程安全的。

可見一陰一陽之謂道,在任何地方都體現(xiàn)得淋漓盡致。

讀書感悟

來自張小嫻《面包樹上的女人》

  • 想要忘記一段感情,方法永遠(yuǎn)只有一個(gè):時(shí)間和新歡。要是時(shí)間和新歡也不能讓你忘記一段感情,原因只有一個(gè):時(shí)間不夠長(zhǎng),新歡不夠好。

  • 我把青春投資在他身上,他成功了,也許會(huì)愛上另一個(gè)女人。他失敗了,我 一無所有。
    愛情太不可靠了,只有事業(yè)才是一份耕耘一份收獲的,我想有自己的事業(yè)。

  • 不能把你留在身邊,不是你的過錯(cuò),而是我的失敗。在你曾經(jīng)愛過我的那些短暫歲月里,我或許是世界上最幸福的人,只是那些日子已成過去,要留也留不住。我知道愛不可以乞求,如果我能夠?yàn)槟阕鲆患拢闶堑却?/p>

  • 一個(gè)男人,泥足深陷地愛上一個(gè)不愛他的女人,注定要放棄自尊.

  • 所有為愛而做的事,都不是壞事.

  • 那時(shí),我已經(jīng)明白,作為一個(gè)女人,你最好很出色,或者很漂亮

其他

如果有帶給你一絲絲小快樂,就讓快樂繼續(xù)傳遞下去,歡迎轉(zhuǎn)載,點(diǎn)贊,頂,歡迎留下寶貴的意見,多謝支持!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容