[[Javaメモ]] > Javaの文字列結合いろいろ
* Javaの文字列結合いろいろ [#vc664b03]
#setlinebreak(on);

Javaでいろいろな方法で文字列結合するメモ。

#contents

** 文字列をそのまま結合する。 [#pe4c683e]
#html(<div style="padding:5px;">)
下記のように、文字列を + で結合すると別のStringインスタンスが生成されてしまう為、メモリ、速度の両面でコストが悪くなる。&br;※コンパイル時に StringBuilder での結合に変換されるが、下記の書き方だと StringBuilderインスタンスをいくつも生成する事になる為、どちらにしても効率が悪い。
#mycode{{
String strAll   = str1;
         strAll += "と";
         strAll += str2;
         strAll += "と";
         strAll += str3;
         strAll += "を結合";
}}
#html(</div>)

** String.concat を使う。 [#r5a5fa5c]
#html(<div style="padding:5px;">)
速度、メモリ消費とも Stringで結合するよりは良い。
#mycode{{
String strAll = str1;
         strAll.concat("と");
         strAll.concat(str2);
         strAll.concat("と");
         strAll.concat(str3);
         strAll.concat("を結合");
}}
#html(</div>)

** StringBuilder (StringBuffer) を使う。 [#cbaac972]
#html(<div style="padding:5px;">)
String.concat よりさらに良い。(同期が必要な場合のみStringBufferを使用する)
#mycode{{
StringBuilder sb = new StringBuilder(str1);
sb.append("と");
sb.append(str2);
sb.append("と");
sb.append(str3);
sb.append("を結合");
String strAll = sb.toString();
}}

*** StringBuilder (StringBuffer) を使う場合に気を付ける事。 [#cbaac972]
#html(<div style="padding:5px;">)
以下のように Stringを文字列結合したものを append してしまうと、&br;Stringの文字列結合部分が StringBuilder での結合に変換される為、無駄にStringBuilderインスタンスが生成されてしまう。
#mycode{{
StringBuilder sb = new StringBuilder("文字列1");
sb.append("文字列2" + val1 + "文字列3");    // <-- この部分の結合用に別のStringBuilder が生成される。
String strAll = sb.toString();
}}

やるなら全て append する事。
#mycode{{
StringBuilder sb = new StringBuilder("文字列1");
sb.append("文字列2").append(val).append("文字列3");
String strAll = sb.toString();
}}
#html(</div>)
#html(</div>)

** 普通に文字列結合してもString インスタンスを無駄に生成しない書き方 [#s53b697b]
#html(<div style="padding:5px;">)
文字列を結合する際に、''セミコロンで区切らずに結合する''とコンパイル時に StringBuilderを使用したイイ感じの結合に変換される。
#mycode{{
String strAll = str1
                  + "と"
                  + str2
                  + "と"
                  + str3
                  + "を結合";
}}
#html(</div>)

#html(<div style="padding:5px;">)
下記の example1 と example2 は等価となる。
#mycode{{
public String example1(String s01, String s02, String s03){
	String strAll = s01
	                   + "と"
                           + s02
	                   + "と"
                           + s03
	                   + "を結合";
    return strAll;
}

// なぜ String.valueOf を使用するように変換されるのかは謎。
public String example2(String s01, String s02, String s03){
	String strAll = new StringBuilder(String.valueOf(s01))
	.append("と")
	.append(s02)
	.append("と")
	.append(s03)
	.append("を結合")
	.toString();
	return strAll;
}
}}
#html(</div>)

#html(<div style="padding:5px;">)
バイトコードの確認結果は以下の通り。

ただ、コンパイラ(環境)による変換をアテにするよりも明示的にStringBuilderを使用してコーディングした方が良いとは思う。&br;というか、実際には条件分岐が入ったりして、なかなかセミコロンなしで一息で書けるようなケースは少ないように思う。
#mycode{{
public java.lang.String example1(java.lang.String, java.lang.String, java.lang.String);
  Code:
   0:	new	#27; //class java/lang/StringBuilder
   3:	dup
   4:	aload_1
   5:	invokestatic	#29; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8:	invokespecial	#35; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   11:	ldc	#60; //String と
   13:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:	aload_2
   17:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   20:	ldc	#60; //String と
   22:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   25:	aload_3
   26:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   29:	ldc	#62; //String を結合
   31:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   34:	invokevirtual	#42; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   37:	astore	4
   39:	aload	4
   41:	areturn

public java.lang.String example2(java.lang.String, java.lang.String, java.lang.String);
  Code:
   0:	new	#27; //class java/lang/StringBuilder
   3:	dup
   4:	aload_1
   5:	invokestatic	#29; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8:	invokespecial	#35; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   11:	ldc	#60; //String と
   13:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:	aload_2
   17:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   20:	ldc	#60; //String と
   22:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   25:	aload_3
   26:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   29:	ldc	#62; //String を結合
   31:	invokevirtual	#38; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   34:	invokevirtual	#42; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   37:	astore	4
   39:	aload	4
   41:	areturn
}
}}

#html(</div>)

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS