String、StringBuilder、StringBuffer

相信你們看到過不少比較String和StringBuffer區別的文章,也明白這二者的區別,然而自從Java 5.0發佈之後,咱們的比較列表上將多出一個對象了,這就是StringBuilder類。String類是不可變類,任何對String的改變都會引起新的String對象的生成;而StringBuffer則是可變類,任何對它所指代的字符串的改變都不會產生新的對象,可變和不可變類這一對對象已經齊全了,那麼爲何還要引入新的StringBuilder類幹嘛?相信你們都有此疑問,我也如此。下面,咱們就來看看引入該類的緣由。安全

      爲何會出現那麼多比較String和StringBuffer的文章?多線程

      緣由在於當改變字符串內容時,採用StringBuffer能得到更好的性能。既然是爲了得到更好的性能,那麼採用StringBuffer可以得到最好的性能嗎?app

      答案是NO!性能

      爲何?ui

      若是你讀過《Think in Java》,並且對裏面描述HashTable和HashMap區別的那部分章節比較熟悉的話,你必定也明白了緣由所在。對,就是支持線程同步保證線程安全而致使性能降低的問題。HashTable是線程安全的,不少方法都是synchronized方法,而HashMap不是線程安全的,但其在單線程程序中的性能比HashTable要高。StringBuffer和StringBuilder類的區別也在於此,新引入的StringBuilder類不是線程安全的,但其在單線程中的性能比StringBuffer高。若是你對此不太相信,能夠試試下面的例子:線程

public class StringTest {
    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 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 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(StringTest.appendItemsToStirngBuffer(list));
    }

    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(StringTest.appendItemsToStirngBuffer(list));
    }

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

上面的程序結果以下:
782 millis has elapsed when used String. 
60 millis has elapsed when used StringBuffer. 
20 millis has elapsed when used StringBuilder. 
I play Bourgeois guitars and Huber banjos 
I play Bourgeois guitars and Huber banjos 
從上面的結果來看,這三個類在單線程程序中的性能差異一目瞭然,採用String對象時,即便運行次數僅是採用其餘對象的1/100,其執行時間仍然比其餘對象高出13倍以上;而採用StringBuffer對象和採用StringBuilder對象的差異也比較明顯,前者是後者的3倍左右。因而可知,若是咱們的程序是在單線程下運行,或者是沒必要考慮到線程同步問題,咱們應該優先使用StringBuilder類;固然,若是要保證線程安全,天然非StringBuffer莫屬了。對象

除了對多線程的支持不同外,這兩個類的使用幾乎沒有任何差異,上面的例子就是個很好的說明。appendItemsToStringBuiler和appendItemsToStirngBuffer兩個方法除了採用的對象分別爲StringBuilder和StringBuffer外,其餘徹底相同,而效果也徹底相同。字符串

相關文章
相關標籤/搜索