StringBuffer の速さ、String.replace の遅さ

一つの String に対していろいろな置換を行った結果を得たいとき、
String.replace を繰り返し適用すると、無駄な時間がかかる。
これは、

  • String オブジェクトが置換の回数だけ生成される
  • String.replace が正規表現置換 (String.replaceAll 相当) を内部で使っている (おそらくこの点は、JDKの実装に依存する)

ことに起因する。

import java.util.Map;
import java.util.HashMap;

public class T {
    static Map<String,String> mapping;
    static {
        mapping = new HashMap<String,String>();
        mapping.put("1", "one");
        mapping.put("2", "two");
        mapping.put("3", "three");
        mapping.put("4", "four");
    }
    static String exec1(String arg){
        String result = arg;
        for (Map.Entry<String, String> m : mapping.entrySet()) {
            int i;
            while ( ( i = result.indexOf(m.getKey())) >= 0 ) {
                result = result.substring(0, i) + m.getValue() + result.substring(i+m.getKey().length());
            }
            //result = result.replace(m.getKey(), m.getValue());
        }
        return result;
    }
    static String exec2(CharSequence arg){
        StringBuffer result = new StringBuffer(arg);
        for (Map.Entry<String, String> m : mapping.entrySet()) {
            int i;
            while ( ( i = result.indexOf(m.getKey())) >= 0 ) {
                result.replace(i, i+m.getKey().length(), m.getValue());
            }
        }
        return result.toString();
    }
    public static void main(String[] args) throws InterruptedException {
        String s = "";
        for ( int i = 0; i < 500000; i++ ) {
            s = exec2("123412341234123412341234123412341234");
        }
        Thread.sleep(s.length()/100);
    }
}