posts - 6,comments - 2,trackbacks - 0

          String和StringBuffer的區(qū)別,網(wǎng)上資料可以說是數(shù)不勝數(shù),但是看到這篇文章,感覺里面做的小例子很有代表性,所以轉(zhuǎn)一下,并自己做了一點(diǎn)總結(jié)。

          在java中有3個(gè)類來負(fù)責(zé)字符的操作。

          1.Character 是進(jìn)行單個(gè)字符操作的,

          2.String 對一串字符進(jìn)行操作。不可變類。

          3.StringBuffer 也是對一串字符進(jìn)行操作,但是可變類。

          String:
          是對象不是原始類型.
          為不可變對象,一旦被創(chuàng)建,就不能修改它的值.
          對于已經(jīng)存在的String對象的修改都是重新創(chuàng)建一個(gè)新的對象,然后把新的值保存進(jìn)去.
          String 是final類,即不能被繼承.

          StringBuffer:
          是一個(gè)可變對象,當(dāng)對他進(jìn)行修改的時(shí)候不會像String那樣重新建立對象
          它只能通過構(gòu)造函數(shù)來建立,
          StringBuffer sb = new StringBuffer();
          note:不能通過付值符號對他進(jìn)行付值.
          sb = "welcome to here!";//error
          對象被建立以后,在內(nèi)存中就會分配內(nèi)存空間,并初始保存一個(gè)null.向StringBuffer
          中付值的時(shí)候可以通過它的append方法.
          sb.append("hello");

          字符串連接操作中StringBuffer的效率要比String高:

          String str = new String("welcome to ");
          str += "here";
          的處理步驟實(shí)際上是通過建立一個(gè)StringBuffer,讓侯調(diào)用append(),最后
          再將StringBuffer toSting();
          這樣的話String的連接操作就比StringBuffer多出了一些附加操作,當(dāng)然效率上要打折扣.

          并且由于String 對象是不可變對象,每次操作Sting 都會重新建立新的對象來保存新的值.
          這樣原來的對象就沒用了,就要被垃圾回收.這也是要影響性能的.

          看看以下代碼:
          將26個(gè)英文字母重復(fù)加了5000次,

          1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
          2.         int times = 5000;
          3.         long lstart1 = System.currentTimeMillis();
          4.         String str = "";
          5.         for (int i = 0; i < times; i++) {
          6.             str += tempstr;
          7.         }
          8.         long lend1 = System.currentTimeMillis();
          9.         long time = (lend1 - lstart1);
          10.         System.out.println(time);

          可惜我的計(jì)算機(jī)不是超級計(jì)算機(jī),得到的結(jié)果每次不一定一樣一般為 46687左右。
          也就是46秒。
          我們再看看以下代碼

          1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
          2.         int times = 5000;
          3.         long lstart2 = System.currentTimeMillis();
          4.         StringBuffer sb = new StringBuffer();
          5.         for (int i = 0; i < times; i++) {
          6.             sb.append(tempstr);
          7.         }
          8.         long lend2 = System.currentTimeMillis();
          9.         long time2 = (lend2 - lstart2);
          10.         System.out.println(time2);

          得到的結(jié)果為 16 有時(shí)還是 0
          所以結(jié)論很明顯,StringBuffer 的速度幾乎是String 上萬倍。當(dāng)然這個(gè)數(shù)據(jù)不是很準(zhǔn)確。因?yàn)檠h(huán)的次數(shù)在100000次的時(shí)候,差異更大。不信你試試。

          根據(jù)上面所說:

          str += "here";
          的處理步驟實(shí)際上是通過建立一個(gè)StringBuffer,讓侯調(diào)用append(),最后
          再將StringBuffer toSting();

          所以str += "here";可以等同于

          StringBuffer sb = new StringBuffer(str);

          sb.append("here");

          str = sb.toString();

          所以上面直接利用"+"來連接String的代碼可以基本等同于以下代碼

          1.         String tempstr = "abcdefghijklmnopqrstuvwxyz";
          2.         int times = 5000;
          3.         long lstart2 = System.currentTimeMillis();
          4.         String str = "";
          5.         for (int i = 0; i < times; i++) {
          6.             StringBuffer sb = new StringBuffer(str);
          7.             sb.append(tempstr);
          8.             str = sb.toString();
          9.         }
          10.         long lend2 = System.currentTimeMillis();
          11.         long time2 = (lend2 - lstart2);
          12.         System.out.println(time2);

          平均執(zhí)行時(shí)間為46922左右,也就是46秒。

          總結(jié): 如果在程序中需要對字符串進(jìn)行頻繁的修改連接操作的話.使用StringBuffer性能會更高

          ===========================================================================================


          自從Java 5.0發(fā)布以后,我們的比較列表上將多出一個(gè)對象了,這就是StringBuilder類。String類是不可變類,任何對String的改變都會引發(fā)新的String對象的生成;而StringBuffer則是可變類,任何對它所指代的字符串的改變都不會產(chǎn)生新的對象,可變和不可變類這一對對象已經(jīng)齊全了,那么為什么還要引入新的StringBuilder類干嗎?相信大家都有此疑問,我也如此。下面,我們就來看看引入該類的原因。

                為什么會出現(xiàn)那么多比較String和StringBuffer的文章?

                原因在于當(dāng)改變字符串內(nèi)容時(shí),采用StringBuffer能獲得更好的性能。既然是為了獲得更好的性能,那么采用StringBuffer能夠獲得最好的性能嗎?

                答案是NO!

                為什么?

                如果你讀過《Think in Java》,而且對里面描述HashTable和HashMap區(qū)別的那部分章節(jié)比較熟悉的話,你一定也明白了原因所在。對,就是支持線程同步保證線程安全而導(dǎo)致性能下降的問題。HashTable是線程安全的,很多方法都是synchronized方法,而HashMap不是線程安全的,但其在單線程程序中的性能比HashTable要高。StringBuffer和StringBuilder類的區(qū)別也在于此,新引入的StringBuilder類不是線程安全的,但其在單線程中的性能比StringBuffer高。如果你對此不太相信,可以試試下面的例子:

          package com.hct.test;

          import java.util.ArrayList;
          import java.util.Iterator;
          import java.util.List;

          /**
          * @author: chengtai.he
          * @created:2009-12-9 上午09:59:57
          */
          public class StringBuilderTester {
          private static final String base = " base string. ";
          private static final int count = 2000000;

          public static void stringTest() {
            long begin, end;
            begin = System.currentTimeMillis();
            String test = new String(base);
            for (int i = 0; i < count/100; i++) {
             test = test + " add ";
            }
            end = System.currentTimeMillis();
            System.out.println((end - begin)
              + " millis has elapsed when used String. ");
          }

          public static void stringBufferTest() {
            long begin, end;
            begin = System.currentTimeMillis();
            StringBuffer test = new StringBuffer(base);
            for (int i = 0; i < count; i++) {
             test = test.append(" add ");
            }
            end = System.currentTimeMillis();
            System.out.println((end - begin)
              + " millis has elapsed when used StringBuffer. ");
          }

          public static void stringBuilderTest() {
            long begin, end;
            begin = System.currentTimeMillis();
            StringBuilder test = new StringBuilder(base);
            for (int i = 0; i < count; i++) {
             test = test.append(" add ");
            }
            end = System.currentTimeMillis();
            System.out.println((end - begin)
              + " millis has elapsed when used StringBuilder. ");
          }

          public static String appendItemsToStringBuiler(List list) {
            StringBuilder b = new StringBuilder();

            for (Iterator i = list.iterator(); i.hasNext();) {
             b.append(i.next()).append(" ");
            }

            return b.toString();
          }

          public static void addToStringBuilder() {
            List list = new ArrayList();
            list.add(" I ");
            list.add(" play ");
            list.add(" Bourgeois ");
            list.add(" guitars ");
            list.add(" and ");
            list.add(" Huber ");
            list.add(" banjos ");

            System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
          }

          public static String appendItemsToStirngBuffer(List list) {
            StringBuffer b = new StringBuffer();

            for (Iterator i = list.iterator(); i.hasNext();) {
             b.append(i.next()).append(" ");
            }

            return b.toString();
          }

          public static void addToStringBuffer() {
            List list = new ArrayList();
            list.add(" I ");
            list.add(" play ");
            list.add(" Bourgeois ");
            list.add(" guitars ");
            list.add(" and ");
            list.add(" Huber ");
            list.add(" banjos ");

            System.out.println(StringBuilderTester.appendItemsToStirngBuffer(list));
          }

          public static void main(String[] args) {
            stringTest();
            stringBufferTest();
            stringBuilderTest();
            addToStringBuffer();
            addToStringBuilder();
          }
          }

          上面的程序結(jié)果如下:
          5266 millis has elapsed when used String.
          375 millis has elapsed when used StringBuffer.
          281 millis has elapsed when used StringBuilder.
          I   play   Bourgeois   guitars   and   Huber   banjos 
          I   play   Bourgeois   guitars   and   Huber   banjos
          從上面的結(jié)果來看,這三個(gè)類在單線程程序中的性能差別一目了然,采用String對象時(shí),即使運(yùn)行次數(shù)僅是采用其他對象的1/100,其執(zhí)行時(shí)間仍然比其他對象高出25倍以上;而采用StringBuffer對象和采用StringBuilder對象的差別也比較明顯,前者是后者的1.5倍左右。由此可見,如果我們的程序是在單線程下運(yùn)行,或者是不必考慮到線程同步問題,我們應(yīng)該優(yōu)先使用StringBuilder類;當(dāng)然,如果要保證線程安全,自然非StringBuffer莫屬了。

          除了對多線程的支持不一樣外,這兩個(gè)類的使用幾乎沒有任何差別,上面的例子就是個(gè)很好的說明。appendItemsToStringBuiler和appendItemsToStirngBuffer兩個(gè)方法除了采用的對象分別為StringBuilder和StringBuffer外,其他完全相同,而效果也完全相同。


          posted on 2012-09-24 09:44 achan2bj 閱讀(140) 評論(0)  編輯  收藏 所屬分類: java SE
          主站蜘蛛池模板: 会同县| 赞皇县| 宣汉县| 四平市| 威宁| 青龙| 巴林右旗| 大名县| 浪卡子县| 宿松县| 阳春市| 进贤县| 五莲县| 桑日县| 响水县| 全南县| 磐石市| 商河县| 阿拉善右旗| 宾阳县| 乳山市| 绥滨县| 吴旗县| 安康市| 平阴县| 塘沽区| 花垣县| 井冈山市| 喀喇| 巴东县| 青冈县| 安仁县| 扎兰屯市| 上思县| 乳源| 调兵山市| 海门市| 嘉禾县| 舟曲县| 银川市| 高碑店市|