Java 字串拼接效率比較
阿新 • • 發佈:2019-02-05
1 字串拼接的三種方法
① 加號
② concat方法
③ StringBuilder(或StringBuffer)的append方法
2 程式例子
package com.jtzen9;
public class Main {
public static void main(String[] args) {
String str = "a";
long time = System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
str += "c" ;
}
System.out.println("加號所花費的時間:");
System.out.println(System.currentTimeMillis()-time);
String str2 = "a";
time = System.currentTimeMillis();
for (int i = 0; i < 50000; i++) {
str2.concat("c");
}
System.out.println("cancat方法所花費的時間:" );
System.out.println(System.currentTimeMillis()-time);
time = System.currentTimeMillis();
StringBuilder stringBuilder = new StringBuilder("a");
for (int i = 0; i < 50000; i++) {
stringBuilder.append("c");
}
String str3 = stringBuilder.toString();
System.out.println("StringBuilder的append方法:" );
System.out.println(System.currentTimeMillis()-time);
}
}
程式輸出:
3 append方法最快、concat次之、加號最慢
3.1 “+”方法
雖然編譯器對字串的加號做了優化,它會使用StringBuilder的append方法進行追加,而它最終通過toString方法轉換成String字串,上例中“+”拼接的程式碼即如下:
str = new StringBuilder(str).append("JTZen9").toString();
它與純粹地使用StringBuilder的append方法是不同的:
① 每趟迴圈都會建立一個StringBuilder物件
② 每次執行完畢都會呼叫toString方法將其轉換為字串
所以,就耗費了更多的時間。
3.2 concat方法
concat原始碼:
public String concat(String str) {
// 追加的字串長度為0
int otherLen = str.length();
// 如果追加的字串長度為0,則返回原字串本身
if (otherLen == 0) {
return this;
}
// 獲取原字串的字元陣列的長度
int len = value.length;
// 將原字串的字元陣列放到buf陣列中
char buf[] = Arrays.copyOf(value, len + otherLen);
// 追加的字串轉化成字元陣列,新增到buf中
str.getChars(buf, len);
// 產生一個新的字串
return new String(buf, true);
}
整體是一個數組的拷貝,雖然在記憶體中是處理都是原子性操作,速度非常快,但是,最後的return語句建立一個新String物件,也就是每次concat操作都會建立一個新的String物件,這也是限制concat方法速度的原因。
3.3 append方法
append原始碼:
public AbstractStringBuilder append(String str) {
// 如果是null值,則把null作為字串處理
if (str == null)
return appendNull();
int len = str.length();
// 追加後的字元陣列長度是否超過當前值
ensureCapacityInternal(count + len);
// 字串複製到目標陣列
str.getChars(0, len, value, count);
count += len;
return this;
}
private AbstractStringBuilder appendNull() {
int c = count;
ensureCapacityInternal(c + 4);
final char[] value = this.value;
value[c++] = 'n';
value[c++] = 'u';
value[c++] = 'l';
value[c++] = 'l';
count = c;
return this;
}
private void ensureCapacityInternal(int minimumCapacity) {
// overflow-conscious code
if (minimumCapacity - value.length > 0)
expandCapacity(minimumCapacity); // 加長,並作陣列拷貝
}
整個append方法都在做字元陣列的處理,加長,拷貝等,這些都是基本的資料處理,整個方法內並沒有生成物件。只是最後toString返回一個物件而已。
4 題外
(1)
String str = "My name is ";
str = str + "JTZen9";
相當於 str = new StringBuilder(str).append(“JTZen9”).toString();
也就是說,該str = str + “JTZen9”;語句執行完之後,總共有三個物件。
(2)
String str = "My name is " + "JTZen9";
JVM會直接把str作為一個物件,即 “My name is JTZen9”
5 使用場景
(1)大多數情況,我們使用“+”,符合編碼習慣和我們的閱讀
(2)當在頻繁進行字串的運算(如拼接、替換、刪除等),或者在系統性能臨界的時候,我們可以考慮使用concat或append方法