JAva文字列接合の研究と最適化


Stringはjavaでは可変であり、各Stringを操作する方法は実際には新しいStringオブジェクトを返し、元のStringオブジェクトを達成できないようにします.Stringの接続には、「+」記号を使用する方法と、StringBuilderを使用する方法、Stringのconcatを使用する方法があります.
(1) ‘+’:
'+'の実装を検討するために、次のテストコードを書きます.
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
code 1から「もし‘+’程度に変数がない場合,‘+’の結果は直接得られる.
code 2から,‘+’の左右に変数がある場合,StringBuilderオブジェクトが生成され,そのappendメソッドが呼び出されることが分かる.
1つの継ぎ目Stringの文で、継ぎ目StringにStringオブジェクトがある場合、この文はStringBuilderオブジェクトを生成し、appendメソッドを呼び出す.
ソースコードのループに注意してください.逆コンパイル後、コードには8から35が対応し、StringBuilderオブジェクトがループに含まれているため、上記のコードはStringBuilderオブジェクトを作成しすぎて効率に影響します.
(2) StringBuilder
次に、StringBuilderのappendメソッドを分析します.ソースコードは次のとおりです.
 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メソッド
ソースコードは次のとおりです.
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オブジェクトを作成することです.
結論:
3つの変数を定義します:String a=“a”、b=“b”、c=“c”;
1.String d=a+bのような単純な結合については、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」第4版Strings章を参照します.