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的比較
-
String:不可變字元序列, 效率低,但是複用率高。
-
StringBuffer:可變字元序列、效率較高(增刪)、執行緒安全(方法有synchronized)
-
StringBuilder(JDK1.5):可變字元序列、效率最高、執行緒不安全(方法沒有synchronized)
-
String s = "a"; (建立了一個字串)。String s += "b"; (再次建立字串"ab")。實際上原來的字串"a"已經被丟棄了,建立了一個新的字串"ab"。如果多次執行這種修改操作,就會有大量的副本字串物件被丟棄來記憶體中,降低效率。如果這種情況出現在迴圈語句中,會極大的影響效能。
-
結論:當需要頻繁的修改字串時,不要使用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)); } }