背景
Javaで文字列を連結する際、最も一般的な方法は「+」または「+=」を使用することです。ただし、大量の連結が必要な場合、特にループ内で連結を行うとパフォーマンス問題が生じることがあります。
テストデータ
- 100,000回のループで文字列連結を行い、「+=」、
StringBuilder、StringBufferのパフォーマンスを比較します。 - JDK 8上で実行し、ループの所要時間を計測します。
具体的な実装
「+=」を使用した文字列連結
@Test
public void testConcatenationWithPlus() {
String result = "";
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
result += i;
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
StringBuilderを使用した文字列連結
@Test
public void testConcatenationWithStringBuilder() {
StringBuilder builder = new StringBuilder();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
builder.append(i);
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
StringBufferを使用した文字列連結
@Test
public void testConcatenationWithStringBuffer() {
StringBuffer buffer = new StringBuffer();
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
buffer.append(i);
}
long endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
}
結果比較
- 「+=」を使用した場合: 18,301 ミリ秒
StringBuilder: 5 ミリ秒StringBuffer: 6 ミリ秒
原理分析
100,000回のループで連結を行った結果、単純に「+=」を使用した場合、他の方法と比べて約3,600倍遅くなりました。これは、各ループで新しいStringBuilderオブジェクトが生成され、それをStringに変換して代入するためのオブジェクト生成のコストが大きいからです。
一方、StringBuilderやStringBufferは、初期容量を設定することで再割り当てのコストを抑えることができます。
StringBufferはスレッドセーフですが、JDK 1.6以降のロック最適化によりパフォーマンスが大幅に向上しました。ただし、並行処理が不要な場合はStringBuilderを使用することが推奨されます。
解決策
大量の文字列連結が必要な場合、特にループ内で連結を行う場合は、StringBuilderやStringBufferを使用することを検討してください。