<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Vincent.Chan‘s Blog

    常用鏈接

    統(tǒng)計(jì)

    積分與排名

    網(wǎng)站

    最新評(píng)論

    如何有效率地使用字串

    原文刊登在 2002/09/26 Java 週報(bào)上

    看完上篇(請(qǐng)參考九月十二日的Java週報(bào))筆者所講解的物件的比較之後,
    既然講到了字串,筆者就再來(lái)跟大家討論一下,如何有效率地使用字串。
    你也許會(huì)有疑問(wèn)說(shuō),字串就這樣用啊,什麼叫有效率的使用字串呢?我們
    先來(lái)確定一件事情,Java API說(shuō)明文件上有這麼一行字:

    “Strings are constant; their values cannot be changed after they are created.
    String buffers support mutable strings. Because String objects
    are immutable they can be shared.”。

    意思是字串是個(gè)常數(shù),是不可
    更改的,也就是說(shuō)你對(duì)一個(gè)字串物件做任何的修改,像是加上另一個(gè)串、
    把字母變大寫(xiě)等等,都會(huì)產(chǎn)生一個(gè)新的字串物件。我們做個(gè)小小的測(cè)試,
    來(lái)証明這件事情。

    								String str1 = newString(“hello”);
    String str2 = str2;
    boolean b1 = str1 == str2;

    還記得上週筆者講解的字串之間比較嗎?b1得到的結(jié)果是true,代表str1
    和str2參考到同一個(gè)字串物件,忘記或是不清楚的讀者,再回去翻翻週報(bào)
    的內(nèi)容。如果現(xiàn)在我們把str2加上“java”這個(gè)字串:

    str2 = str2 + “java”;
    boolean b2 = str1 == str2;

    你會(huì)發(fā)現(xiàn)b2的結(jié)果是false,代表str1和str2所參考的字串物件已經(jīng)不是同
    一個(gè)了!現(xiàn)在在系統(tǒng)中就有三個(gè)字串物件,一個(gè)是“hello”,第二個(gè)是“
    java”,第三個(gè)是“hellojava”。因?yàn)樵贘ava中,字串有這樣一個(gè)不可修
    改的特性,所以才會(huì)引發(fā)出如何有效地使用字串這個(gè)問(wèn)題出來(lái)。

    字串是每個(gè)應(yīng)用程式都會(huì)用到的物件,常常有些程式中會(huì)對(duì)字串做大量的
    運(yùn)算,尤其是兩個(gè)字串的相加,例如我們寫(xiě)了一個(gè)從網(wǎng)路上讀取網(wǎng)頁(yè)資料
    的程式,跑個(gè)迴圈,用BufferedReader物件一次讀一行進(jìn)來(lái),然後把每一
    行再加在一起。像這種很直覺(jué)、很簡(jiǎn)單的程式,兩行就搞定了,可是JVM中
    所做的事情可多了。 假設(shè)我們寫(xiě)個(gè)一程式,要把一個(gè)字串一直加上“a”
    一百次,很直覺(jué)得我們會(huì)這樣寫(xiě):

    								String str = “”;
    for (int i=0; i<100; i++)
    str += “a”;

    可是你知道在記憶體中會(huì)產(chǎn)生多少的垃圾出來(lái)嗎?總共會(huì)有a、aa、aaa、
    aaa….,無(wú)疑的,上述的程式雖然簡(jiǎn)單,但浪費(fèi)了不少的記憶體,而且產(chǎn)
    生物件和物件的存取也會(huì)花掉不少的時(shí)間,我們加上幾行程式碼來(lái)測(cè)試所
    花的時(shí)間和記憶體:

    								long startTime = System.currentTimeMillis();
    long startMem = Runtime.getRuntime().freeMemory();

    for (int i=0; i<1000; i++)
    str += "a";

    long endMem = Runtime.getRuntime().freeMemory();
    System.out.println("Use memory: "+ (startMem - endMem));
    long endTime = System.currentTimeMillis();
    System.out.println("Use Time: "+ (endTime – startTime));

    上面的程式在筆者的PIII-800的電腦上跑,平均花了50 ms和151256 bytes
    的記憶體,時(shí)間還好,但記憶體使用量算蠻大的了。那我們要如何來(lái)改進(jìn)
    讓程式更有效率呢?因?yàn)镾tring物件是不可修改的,可是程式中又常需要
    這樣的一個(gè)動(dòng)作,所以Java提供了另外一個(gè)類別,專門來(lái)處理字串運(yùn)算用
    的,這個(gè)類別就叫作StringBuffer。StringBuffer類別提供了很多方法來(lái)
    做字串的運(yùn)算,但如附加、刪除、插入、反轉(zhuǎn)、替換等等…。我們就用
    StringBuffer類別所提供的附加(append)方法來(lái)做到跟上面那個(gè)例子同樣
    的結(jié)果:

    								StringBuffer sb = newStringBuffer();
    long startTime = System.currentTimeMillis();
    long startMem = Runtime.getRuntime().freeMemory();

    for (int i=0; i<1000; i++)
    sb.append(“a”);

    long endMem = Runtime.getRuntime().freeMemory();
    System.out.println("Use memory: "+ (startMem - endMem));
    long endTime = System.currentTimeMillis();

    修改過(guò)的程式在筆者電腦上跑,平均花了0 ms和4854 bytes的記憶體。
    0 ms?!多跑幾次有時(shí)會(huì)到10 ms,要看你電腦CPU目前的負(fù)載如何,不
    過(guò)跟前面的例子比較起來(lái),已經(jīng)算是快了,而且記憶體也使用的非常少
    。這只是個(gè)小小的例子,如果字串量再大一點(diǎn),兩者的差異會(huì)更明顯。

    所以結(jié)論就是,如果你的程式中會(huì)對(duì)字串做大量的修改時(shí),請(qǐng)改用
    StringBuffer類別,它會(huì)明顯示改進(jìn)你程式的效率。至於StringBuffer
    類別所提供的方法詳細(xì)的使用說(shuō)明,就請(qǐng)自行參閱Java API。



    作者: hkdennis2k

    JDK 5.0 加入了 StringBuilder
    和 StringBuffer 主要不同的時(shí), 它不是 synconized 的, 省回了一點(diǎn) overhead

    javac -target 1.4
    String b=a+"a";

    會(huì)被 compile 為

    								String b=newStringBuffer(a).append("a").toString();
    javac -target 1.5
    String b=a+"a";

    會(huì)被 compile 為

    								String b=new StringBuilder(a).append("a").toString();

    因?yàn)?1.4 沒(méi)有 StringBuilder, 所以 javac -target 1.5 是不可以在 jvm 1.4 上運(yùn)行的

    另外....

    								static
    								final
    								int x=10000;

    StringBuffer sb = newStringBuffer();
    for (int i=0; i<x; i++)
    sb.append(“a”);

    StringBuffer sb = newStringBuffer(x);
    for (int i=0; i<x; i++)
    sb.append(“a”);

    也是相差很遠(yuǎn)的...
    好像大約 20%

    想想 String b=new StringBuilder(a).append("a").toString(); 吧
    在大型的 loop 中, 這是突破 preformenace 的一個(gè)關(guān)口....



    作者: hkdennis2k

    StringBuilder 內(nèi)部是用 char[] 實(shí)作, 而 default 只是用 char[16],
    似類似 ArrayList, 當(dāng) char[] 長(zhǎng)度不足就會(huì)用 System.arraycopy 移到另一個(gè)新的使用

    								StringBuffer sb = newStringBuffer();
    for (int i=0; i<x; i++)
    sb.append("a");

    而這段 code, 會(huì)出現(xiàn)大當(dāng) arraycopy, new char[] 等等浪費(fèi)時(shí)間的動(dòng)作
    連 GC 做的份也少省了下來(lái)

    								StringBuffer sb = newStringBuffer(x);

    而這個(gè), 一開(kāi)始就準(zhǔn)備了一個(gè)剛好足夠大小的 char[]

    也就是, 和 ArrayList, HashMap 之類的, 利用 init 一個(gè)比較大/剛好的 array 來(lái)減少 rehash / overhead的原理一樣, 不過(guò) StringBuffer 沒(méi)法字去更改 resize factor 就是了....

    void expandCapacity(int minimumCapacity) {
    int newCapacity = (value.length + 1) * 2;
    if (newCapacity < 0) {
    newCapacity = Integer.MAX_VALUE;
    } elseif (minimumCapacity > newCapacity) {
    newCapacity = minimumCapacity;
    }
    char newValue[] = newchar[newCapacity];
    System.arraycopy(value, 0, newValue, 0, count);
    value = newValue;
    }
    publicStringBuffer append(String str) {
    if (str == null) str = "null";
    int len = str.length();
    if (len == 0) returnthis;
    int newCount = count + len;
    if (newCount > value.length)
    expandCapacity(newCount);
    str.getChars(0, len, value, count);
    count = newCount;
    returnthis;
    }



    作者: 老陳

    另外再提供一個(gè)技巧,就是比對(duì)空字串的時(shí)候,一般人會(huì)這樣比

    a.equals("")

    但如果改用下列的方式效率會(huì)更好

    a.length() == 0

    雖然""是直接去String pool裡面拿的,不用再去create一個(gè)新的String Object,但是Object的比對(duì)總是要比原生型態(tài)的效率差一點(diǎn)

    以上提供給大家參考. 歡迎大大指較

    posted on 2006-03-23 00:00 Vincent.Chen 閱讀(265) 評(píng)論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 久久亚洲高清观看| 亚洲高清乱码午夜电影网| 日本成年免费网站| 麻豆91免费视频| 99久久亚洲精品无码毛片| 天天拍拍天天爽免费视频| 亚洲精品黄色视频在线观看免费资源 | 亚洲一区二区三区无码中文字幕| 一区二区在线免费观看| 亚洲AV日韩AV一区二区三曲 | 亚洲国产精品成人久久久| 亚洲成av人片不卡无码久久 | 亚洲国产aⅴ综合网| 99爱在线精品视频免费观看9| 久久久亚洲精华液精华液精华液 | 国产精品久久免费| 永久免费无码日韩视频| 亚洲国产91在线| 国产V亚洲V天堂无码久久久| 老司机永久免费网站在线观看| 久久久精品免费视频| 美女视频黄a视频全免费网站色| 中文字幕亚洲综合久久| 亚洲高清偷拍一区二区三区 | 亚洲国产精品无码中文字| 国产免费69成人精品视频| 外国成人网在线观看免费视频 | 国产大片免费网站不卡美女| 中文字幕a∨在线乱码免费看| 亚洲爆乳精品无码一区二区| 亚洲一区二区三区四区在线观看 | 亚洲av无码av在线播放| 亚洲手机中文字幕| 亚洲精品成人网站在线观看| 又大又硬又爽免费视频| 成人一a毛片免费视频| 91短视频免费在线观看| 精品无码人妻一区二区免费蜜桃 | 日韩av无码免费播放| 污污污视频在线免费观看| 亚洲国产午夜精品理论片在线播放|