Java9 で String クラスがリファクタリングされていました。(replace メソッド編)

前々からこの実装はどうなの!?と言われていた String クラスの CharSequence を引数に取る replace メソッド。
これがついに Java 9 でリファクタリングされていました!

今まであった問題

String クラスの replace (CharSequence target, CharSequence replacement) メソッドは、文字列を置換する処理です。
これが、Java 8 までのバージョンでは正規表現を使って実装していました。

public String replace(CharSequence target, CharSequence replacement) {
    return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
            this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}

正規表現は様々な処理ができる反面、かなり重たい処理です。
そのため、このメソッドは大した仕様ではないにも関わらず、あまり速くありませんでした。

Java 9 の実装

Java 9 では、正規表現を使うのをやめて StringBuilder を使うように書き直されていました!

public String replace(CharSequence target, CharSequence replacement) {
    String tgtStr = target.toString();
    String replStr = replacement.toString();
    int j = indexOf(tgtStr);
    if (j < 0) {
        return this;
    }
    int tgtLen = tgtStr.length();
    int tgtLen1 = Math.max(tgtLen, 1);
    int thisLen = length();

    int newLenHint = thisLen - tgtLen + replStr.length();
    if (newLenHint < 0) {
        throw new OutOfMemoryError();
    }
    StringBuilder sb = new StringBuilder(newLenHint);
    int i = 0;
    do {
        sb.append(this, i, j).append(replStr);
        i = j + tgtLen;
    } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0);
    return sb.append(this, i, thisLen).toString();
}

indexOf で文字列を探して、StringBuilder でちょっとずつ結合していくという実装です。
Apache Commons Lang の実装とよく似ています。
たしかにこれらなら速そうです。


念のため、簡単なコードで試してみたところ、文字列の長さや検索する文字列にもよりますが、だいたい2.5倍以上速くなっていました。
特に、文字列がヒットしなかった場合は10倍以上速くなっていました。


これなら安心して使えますね!