Javaの文字列結合について
第3回Effective Java読書会で項目51「文字列結合のパフォーマンスに用心する」がテーマに上がったのでそのあたりのお話を少しまとめておこうかと思います。
まず、Effective Javaの項目51には
ということがかかれています。
1に関して、どのような場合にパフォーマンスに影響を与えるかというと、主に以下のようなループ内で文字列を+演算子で結合する場合があげられると思います。
String result = ""; for( int i = 0; i < 10; i++ ){ result += i; //String結合 }
なぜこのような場合にパフォーマンスに影響を与えるかというと、文字列結合に+演算子を使用した場合にはコンパイル時にStringBuilderのappendメソッドを使用した処理に置き換えられ、実質的に以下のようなコードに変換されます。*1
String result = ""; for( int i = 0; i < 10; i++ ){ StringBuilder sb = new StringBuilder( result ); sb.append( i ); result = sb.toString(); }
n回のループに対してn個のStringBuilderのインスタンスが生成されてしまうことになり、その分処理が遅くなってしまうのは明らかです。
このような場合には2に書かれているようにStringBuilderを使用した処理にしておくのが妥当です。これであればStringBuilderは最初に一つ作るだけで、無駄なStringBuilderのインスタンス生成処理でCPUやメモリ領域が使用されません。
StringBuilder sb = new StringBuilder(); for( int i = 0; i < 10; i++ ){ sb.append( i ); } String result = sb.toString();
ちなみに、StringBuilderとよく似たクラスにStringBufferというクラスがあり、こちらは同期化処理を含んだ実装になっています。しかし、StringBuilder(StringBuffer)を複数のスレッド間で共有するということはまず無いと思うので、基本的にStringBuilderを使っておけば良いと思います。*2
ただし、文字列リテラル(と文字列定数)だけを結合する場合は+演算子を使用したうがパフォーマンスが良かったりします。例えば以下のようなコード
String text2 = "1234" + "5678"; }
であれば、コンパイル時にコンパイラがあらかじめ文字列結合した結果に変換してくれるため、実質的に以下のようなコードに変換されます。
String text2 = "12345678";
}
このような場合なら、わざわざ実行時にStringBuilderを使用して結合するよりかは、+演算子を使用してコンパイル時に結合してしまうほうがパフォーマンスが良いでしょう。
まとめ
Effective Java 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2008/11/27
- メディア: 単行本(ソフトカバー)
- 購入: 71人 クリック: 892回
- この商品を含むブログ (255件) を見る