java 字符串拼接的研究與優化

String 在java中是不可變的,每一個對String進行操做的方法實際上都是返回一個新的String對象,並使原來的String對象不可達。對String的鏈接常有下面幾種方法,一種是使用‘+’符號,另外一種是使用StringBuilder,再就是String的concat方法。 java

(1) ‘+’: app

爲了研究'+'的實現,咱們寫如下測試代碼: 工具

public static void main(String[] args) {
	String a="hell"+"o";   //code1
	String b="world";
	for(int i=0;i<4;i++) {
	   a+=b;             //code2
	}
}
把上面代碼編譯後再用jdk的反編譯工具(javap)反編譯下,獲得以下代碼:
public static void main(java.lang.String[]);
  Code:
   0:    ldc    #16; //String hello
   2:    astore_1
   3:    ldc    #18; //String world
   5:    astore_2
   6:    iconst_0
   7:    istore_3
   8:    goto    33
   11:    new    #20; //class java/lang/StringBuilder
   14:    dup
   15:    aload_1
   16:    invokestatic    #22; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   19:    invokespecial    #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   22:    aload_2
   23:    invokevirtual    #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   26:    invokevirtual    #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   29:    astore_1
   30:    iinc    3, 1
   33:    iload_3
   34:    iconst_4
   35:    if_icmplt    11
   38:    return
從code1能夠獲得「若是在‘+’左右沒有變量的時候,‘+‘的結果是直接得出的。

從code2能夠獲得,若是在‘+’左右有變量的時候,會生成一個StringBuilder對象,而後調用其append方法。 測試

在一個拼接String的語句中,若是被拼接的String中有String對象,那這個語句會生成一個StringBuilder對象,而後調用其append方法. ui

注意源碼中的循環,反編譯後在代碼中對應的是<line>8</line>到<line>35</line>,而建立StringBuilder對象被包含在了循環內,因此上面的代碼會建立過多StringBuilder對象而影響效率。 this

(2) StringBuilder lua

下面咱們來分析下StringBuilder的append方法,其源碼以下: code

public StringBuilder append(String str) {
	super.append(str);
        return this;
    }
super.append(str)以下:
public AbstractStringBuilder append(String str) {
	if (str == null) str = "null";
        int len = str.length();
	if (len == 0) return this;
	int newCount = count + len;
	if (newCount > value.length)
	    expandCapacity(newCount);//此方法拓展StringBuilder的容量至當前容量的2倍
	str.getChars(0, len, value, count);
	count = newCount;
	return this;
    }
經過分析源碼咱們能夠發現StringBuilder的效率是很高的(這也是java編譯器默認採用StringBuilder的緣由),但要注意拓展容量的操做,因此適當設置初始容量是頗有必要的。

(3)String的concat方法 對象

其源碼以下: ci

public String concat(String str) {
	int otherLen = str.length();
	if (otherLen == 0) {
	    return this;
	}
	char buf[] = new char[count + otherLen];
	getChars(0, count, buf, 0);
	str.getChars(0, otherLen, buf, count);
	return new String(0, count + otherLen, buf);
    }

這個方法的做用很簡單,就是建立一個新String對象。

結論:

定義三個變量:String a="a",b="b",c="c";

1.對於簡單拼接,如String d=a+b,建議使用concat方法:String d=a.concat(b);來減小生成沒必要要的StringBuilder對象

2.對於二次以上拼接,如String d=a+b+c,使用這種方式就能夠

3.對於涉及到循環的拼接,如:

String d="";
String e="";
for(int i=0;i<10;i++) {
   d+=a;//或d=d+a;
   e+=(a+b);//或e=e+a+b;
}

建議採用如下方式:

StringBuilder d = new StringBuilder(10)//設置初始容量以減小拓容操做
StringBuilder e = new StringBuilder(20);
for(int i=0;i<10;i++) {
  d.append(a);
  e.append(a).append(b);
}
#本文參考自《thinking in java》第四版Strings章節
相關文章
相關標籤/搜索