1. 程式人生 > 實用技巧 >Java基礎之:StringBuffer與StringBuilder

Java基礎之:StringBuffer與StringBuilder

Java基礎之:StringBuffer與StringBuilder

StringBuffer

StringBuffer是final類,實現了Serializable介面,可以儲存到檔案,或網路傳輸。繼承了抽象類AbstractStringBuilder,StringBuffer繼承了AbstractStringBuilder類的char[] value屬性,用於存放字元。

所以對於Stringbuffer而言,字串是可變的,因為儲存字串的char陣列,沒有被final修飾。

String和StringBuffer的對比

  • String儲存的是字串常量,裡面的值不能更改,每次String類的更新實際上就是更新地址,效率比較低。底層實現是private final char value[];

  • StringBuffer儲存的是字串變數,裡面的值可以更改,每次StringBuffer更新是更新內容,不需要更新地址,效率較高,但對於StringBuffer而言,有一個字串長度的限制,當超過限制時,就需要通過擴容來增加長度。即便如此,也是比String運用起來方便了很多。底層實現時char value[];

在之前的部落格“Java基礎之:OOP——抽象類”中的最後一個案例,就體現了StringBuffer在拼接字串上的速度遠遠優於String。其原理就是因為,StringBuffer底層不是final修飾的char[]陣列。

測試案例

public class StringBuffer {
    public static void main(String[] args) {
​
        // TODO Auto-generated method stub
        long start = System.currentTimeMillis();
        StringBuffer s = new StringBuffer("");
        for (int i = 0; i < 80000; i++) {
            s.append("hello");
        }
        long end = System.currentTimeMillis();
        System.out.println("耗時=" + (end - start) + " length=" + s.length());
    }
}

由於StringBuffer中可以使用的方法大多都與String相同,所以這裡不再介紹。

應用案例

輸入價格,要求列印效果示例 7777123567.59=> 7,777,123,567.59 ;123,564.59 <= 123456.59

package class_StringBuffer;
import java.util.Scanner;
public class ClassWork01 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String in = scanner.next();
        StringBuffer sb = new StringBuffer(in);
        int index = sb.indexOf(".");
        if (index != -1) {
            for (int i = index - 3; i > 0; i -= 3) {    //直接先減掉一個3,就定位到需要插入逗號的位置
                //if (i != index) {
                    sb.insert(i, ",");
                //}
            }
        } else {
            for (int i = 0; i < sb.length(); i += 3) {
                if (i != 0) {
                    sb.insert(i, ",");
                }
            }
        }
        System.out.println(sb);
    }
}

StringBuilder

  • StringBuilder是一個可變的字元序列。此類提供一個與StringBuffer相容的API,但不保證同步(多執行緒問題,即在多個執行緒同時訪問時出現問題)。該類被設計作為StringBuffer的一個簡易替換,用在字串緩衝區被單個執行緒使用的時候。如果不考慮執行緒安全問題,可以優先使用此類,在大多數情況下,它比StringBuffer要快。

  • 在StringBuilder中主要使用的是append與insert方法,可過載這些方法,以接收任何型別的資料。每個方法都能有效地將給定的資料轉換成字串,然後將該字串的字元追加或插入到字串生成器中。append 方法始終將這些字元新增到生成器的末端;而 insert 方法則在指定的點新增字元。

StringBuffer與StringBuilder都是可變序列,所以使用方法上是一樣的。

String、StringBuffer、StringBuilder的比較

  1. String:不可變字元序列, 效率低,但是複用率高。

  2. StringBuffer:可變字元序列、效率較高(增刪)、執行緒安全(方法有synchronized)

  3. StringBuilder(JDK1.5):可變字元序列、效率最高、執行緒不安全(方法沒有synchronized)

  4. String s = "a"; (建立了一個字串)。String s += "b"; (再次建立字串"ab")。實際上原來的字串"a"已經被丟棄了,建立了一個新的字串"ab"。如果多次執行這種修改操作,就會有大量的副本字串物件被丟棄來記憶體中,降低效率。如果這種情況出現在迴圈語句中,會極大的影響效能。

  5. 結論:當需要頻繁的修改字串時,不要使用String型別宣告字串。

測試案例

public class StringVsStringBufferVsStringBuilder {
​
    public static void main(String[] args) {
        // TODO Auto-generated method stub
​
        String text = ""; //字串
        long startTime = 0L;
        long endTime = 0L;
        StringBuffer buffer = new StringBuffer("");//StringBuffer
        StringBuilder builder = new StringBuilder("");//StringBuilder
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 80000; i++) {
            buffer.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuffer的執行時間:" + (endTime - startTime));
        
        
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 80000; i++) {
            builder.append(String.valueOf(i));
        }
        endTime = System.currentTimeMillis();
        System.out.println("StringBuilder的執行時間:" + (endTime - startTime));
        
        
        
        startTime = System.currentTimeMillis();
        for (int i = 0; i < 80000; i++) {
            text = text + i;
        }
        endTime = System.currentTimeMillis();
        System.out.println("String的執行時間:" + (endTime - startTime));
​
    }
}