StringBuilderを使うべきかどうか。

なんか、StringBuilderを使った方が速いって勘違いしている人がいるので、ぐぐってみたら↓あたりが....

この辺、StringとStringBuilderの特性を知らないで計測しているので、Stringの+演算子ががとんでもなく遅いことになっていますけど、全くそんなことないです。問題は2つあって一つがStringの書き方で最適化が効かないような書き方をしている点とStringが不得意な巨大なStringを作り出している点。

一般的にあるような文字列連結なら、最適化が効いてStringBuilderと同じようなコードに置き換えてくれるので、うん百倍の性能差が出ることは無いです。

import java.util.Date;

public class StringPerformance {
	
	public static void main(String[] args) {
		
		long start = 0;
		long loop = 1000000;

		start = now();
		for(int i = 0; i < loop; i++) {
			String s = "abcde";
			s += "1234567890";
			s += "うほうほ";
		}
		long stringResult = now()- start;
		
		start = now();
		for(int i = 0; i < loop; i++) {
			StringBuilder sb = new StringBuilder("abcde");
			sb.append("1234567890");
			sb.append("うほうほ");
			sb.toString();
		}
		long builderResult = now()- start;
		
		start = now();
		for(int i = 0; i < loop; i++) {
			StringBuffer sb = new StringBuffer("abcde");
			sb.append("1234567890");
			sb.append("うほうほ");
			sb.toString();
		}
		long bufferResult = now()- start;
		
		
		System.out.printf("String:%d, Builder:%d, Buffer:%d\n", stringResult, builderResult, bufferResult);
		
	}
	
	private static long now() {
		return new Date().getTime();
	}

}

で、結果。

String:163, Builder:78, Buffer:114

百万回実行しての差がこれだけなので、ほとんど無視してしまっていいレベルの性能差です。というかリテラルを連結する場合などは+演算子でつなげた方が速い場合もあります。なんで、Stringを連結する場合は素直に演算子でつなげて記述性を優先させておきましょう。

StringBuilderを使うべき箇所lはテンプレートエンジンを実装するときとか、巨大なStringを効率よく扱いたい場合とか特別に性能に配慮したい場合だけで十分です。

ちなみに、このバッドノウハウが広がったのは1.4系の頃に最適化の頭が悪くて、Stringの演算子を使った場合にStringBufferオブジェクトを作りまくっている問題があって、演算子の代わりにStringBufferを使うと40倍速い頃があったのが原因で今のVMはそんなことないので−。