字元串的拼接方法一般使用以下五種:
1、String 的加法 "+"
2、String 的concat() 方法
3、StringBuider 的append() 方法
4、StringBuffer 的append() 方法
5、lang3 包中的StringUtils.join() 方法
性能分析:
方法1:String是final類,是不可變的,是以他一旦被執行個體化就無法被修改,是以String字元串的拼接,都是又生成了一個新的字元串,使用“+”進行拼接時,反編譯出的位元組碼檔案顯示先new一個StringBuilder 對象,然後進行append 操作,最後通過toString 方法傳回String 對象,該方法适用于小資料量的操作,代碼友善簡潔,使用該方法更符合我們的編碼和閱讀習慣
String s1 = "";
s1 += "A";
// 反編譯後
s1 = new StringBuilder().append(s1).append("A").toString();
方法2:concat() 方法實作的源代碼如下:
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
通過源代碼可以看出,concat 方法是通過建立一個新的字元數組,然後将原字元串和拼接的字元串的值複制到這個字元數組上,并使用這個字元數組建立一個新的String 對象傳回
方法3:StringBuilder 和 StringBuffer 類與String 類不同,它們并不是final 類,是以它們是可以修改的。它們都封裝了字元數組,append 方法會将字元直接拷貝到内部的字元數組中,如果字元數組的長度達到最大容量時,就會進行擴容,擴充的容量是目前容量的2倍再加2(可以近似的看作2的N次幂),并且會有未被使用的字元空間,是以,StringBuilder預設配置設定16個字元的空間,如果能明确字元的最大空間,建議使用如下方式,避免大量的記憶體空間浪費
new StringBuilder(int size) // 預設配置設定size個字元的空間
方法4:StringBuffer 和StringBuilder 最大的差別是該方法使用了synchronized 進行聲明,是線程級别安全的方法,該類和StringBuilder 類都是繼承自AbstractStringBuilder 類,是以運作效率會比StringBuilder 慢一些
方法5:lang3 包的StringUtils.join() 方法的實作源碼如下所示,從以下的源代碼可以看出,該方法也是通過StringBuilder 來實實作的,(這裡不對該方法做性能比較,了解的朋友看下源代碼就知道性能如何了)
public static <T> String join(T... elements) {
return join((Object[])elements, (String)null);
}
public static String join(Object[] array, String separator) {
return array == null ? null : join((Object[])array, separator, 0, array.length);
}
public static String join(Object[] array, String separator, int startIndex, int endIndex) {
if (array == null) {
return null;
} else {
if (separator == null) {
separator = "";
}
int noOfItems = endIndex - startIndex;
if (noOfItems <= 0) {
return "";
} else {
StringBuilder buf = newStringBuilder(noOfItems);
for(int i = startIndex; i < endIndex; ++i) {
if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
buf.append(array[i]);
}
}
return buf.toString();
}
}
}
批量資料處理的比較:
批量資料的處理一般都會用到周遊,對字元串連接配接應該使用StringBuilder/StringBuffer代替String的連接配接方式。因為在使用String類拼接字元串時,Java虛拟機不僅要花時間生成對象,以後可能還需要花時間對這些對象進行垃圾回收和處理,是以,生成過多的對象将會給程式的性能帶來很大的影響。是以String 不能用來做批量資料的處理。
如下的Demo,數量級十萬,從運作時間很明顯看出性能如何:
public class Test {
public static void main(String[] args) {
String s1 = new String();
String s2 = new String();
StringBuilder sb1 = new StringBuilder();
StringBuffer sb2 = new StringBuffer();
int num = 100000;
long t0 = System.currentTimeMillis();
for (int i = 0; i < num; i++) {
s1 += "A";
}
long t1 = System.currentTimeMillis();
for (int i = 0; i < num; i++) {
s2 = s2.concat("a");
}
long t2 = System.currentTimeMillis();
for (int i = 0; i < num; i++) {
sb1.append("A");
}
long t3 = System.currentTimeMillis();
for (int i = 0; i < num; i++) {
sb2.append("B");
}
long t4 = System.currentTimeMillis();
System.out.println("String [+]\f"+ (t1 - t0)
+ "\nString [concat()]\f" + (t2 - t1)
+ "\nStringBuilder [append()]\f" + (t3 - t2)
+ "\nStringBuffer [append()]\f" + (t4 - t3));
}
}
控制台列印如下:
String [+] 21948
String [concat()] 4179
StringBuilder [append()] 6
StringBuffer [append()] 11