Javaメモ > Javaの文字列結合いろいろ

Javaの文字列結合いろいろ

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

文字列をそのまま結合する。

下記のように、文字列を + で結合すると別のStringインスタンスが生成されてしまう為、メモリ、速度の両面でコストが悪くなる。
※コンパイル時に StringBuilder での結合に変換されるが、下記の書き方だと StringBuilderインスタンスをいくつも生成する事になる為、どちらにしても効率が悪い。

String strAll   = str1;
         strAll += "と";
         strAll += str2;
         strAll += "と";
         strAll += str3;
         strAll += "を結合";

String.concat を使う。

速度、メモリ消費とも Stringで結合するよりは良い。

String strAll = str1;
         strAll.concat("と");
         strAll.concat(str2);
         strAll.concat("と");
         strAll.concat(str3);
         strAll.concat("を結合");

StringBuilder (StringBuffer) を使う。

String.concat よりさらに良い。(同期が必要な場合のみStringBufferを使用する)

StringBuilder sb = new StringBuilder(str1);
sb.append("と");
sb.append(str2);
sb.append("と");
sb.append(str3);
sb.append("を結合");
String strAll = sb.toString();

StringBuilder (StringBuffer) を使う場合に気を付ける事。

以下のように Stringを文字列結合したものを append してしまうと、
Stringの文字列結合部分が StringBuilder での結合に変換される為、無駄にStringBuilderインスタンスが生成されてしまう。

StringBuilder sb = new StringBuilder("文字列1");
sb.append("文字列2" + val1 + "文字列3");    // <-- この部分の結合用に別のStringBuilder が生成される。
String strAll = sb.toString();

やるなら全て append する事。

StringBuilder sb = new StringBuilder("文字列1");
sb.append("文字列2").append(val).append("文字列3");
String strAll = sb.toString();

普通に文字列結合してもString インスタンスを無駄に生成しない書き方

文字列を結合する際に、セミコロンで区切らずに結合するとコンパイル時に StringBuilderを使用したイイ感じの結合に変換される。

String strAll = str1
                  + "と"
                  + str2
                  + "と"
                  + str3
                  + "を結合";

下記の example1 と example2 は等価となる。

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;
}

バイトコードの確認結果は以下の通り。

ただ、コンパイラ(環境)による変換をアテにするよりも明示的にStringBuilderを使用してコーディングした方が良いとは思う。
というか、実際には条件分岐が入ったりして、なかなかセミコロンなしで一息で書けるようなケースは少ないように思う。

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
}

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-05-15 (水) 03:43:46 (4171d)