LoginSignup
2
2

More than 5 years have passed since last update.

プレフィックスの除去はどの方法が最速か?

Last updated at Posted at 2016-08-04

仕事で少し迷ったので調べてみた。

環境

  • OS ・・・ Mac OS X
  • CPU ・・・ 1.7 GHz Intel Core i7
  • Java ・・・ jdk 8u73

コード

public class Test {

    static final String TEXT = "prefix_ABCDEFG";
    static final String PREFIX = "prefix_";
    static final String REGEXP_PREFIX = "^prefix_";
    static final String EMPTY = "";

    public static void main(String[] args) {
        IntStream.rangeClosed(0, 10).forEach(i -> {
            exec("warm up", Test::test_replace);
            exec("replace + startsWith", Test::test_replace);
            exec("replaceAll", Test::test_replaceAll);
            exec("replaceFirst", Test::test_replaceFirst);
            exec("substring + startsWith", Test::test_substringIfStartsWith);
        });
    }

    static void exec(String test, Consumer<String> cons) {
        //ウォームアップ
        IntStream.of(20).forEach(i -> cons.accept(TEXT));

        long start = System.nanoTime();
        IntStream.rangeClosed(0, 1_000_000).forEach(i -> cons.accept(TEXT));
        long time = System.nanoTime() - start;

        System.out.println(String.format("%s : %d ms", 
                                        test, time /1000 ));
    }

    static void test_replace(String text) {
        if(!text.startsWith(PREFIX)) return;
        text.replace(PREFIX, EMPTY);
    }

    static void test_replaceAll(String text) {
        text.replaceAll(REGEXP_PREFIX, EMPTY);
    }

    static void test_replaceFirst(String text) {
        text.replaceFirst(REGEXP_PREFIX, EMPTY);
    }

    static void test_substringIfStartsWith(String text) {
        if(!text.startsWith(PREFIX)) return;
        text.substring(PREFIX.length(), TEXT.length());
    }

}

結果

パターン 速度(平均)
replace + startsWith 367775 ms
replaceAll 353670 ms
replaceFirst 346915 ms
substring + startsWith 16816 ms

まあ、replaceは正規表現つかってますからね。。
ということでパフォーマンスが求められる箇所はsubstringですね。

追記

@kazuki43zoo さんにコメントでご指摘いただいたので。
String.replaceが遅い原因として、実行するごとに毎回正規表現をコンパイルしていることが挙げられます。
したがって、正規表現をあらかじめコンパイルして使い回せばより速くなることが期待できます。

上記のコードに次のメソッドを足します。

    static Pattern pattern = Pattern.compile(REGEXP_PREFIX);

    static void test_pattern_replaceAll(String text) {
        pattern.matcher(text).replaceAll(EMPTY);
    }

    static void test_pattern_replaceFirst(String text) {
        pattern.matcher(text).replaceFirst(text);
    }

結果

パターン 速度(平均)
replace + startsWith 367898 ms
replaceAll 362225 ms
replaceFirst 334916 ms
substring + startsWith 16061 ms
Pattern.replaceAll 179644 ms
Pattern.replaceFirst 237790 ms

とまあreplaceAllについては約2倍の実行速度になりました。
replaceFirstも2倍とまではいきませんが、確実に速くなっています。
ですが、やっぱりsubstringが最速なのは同じですね^^;

2
2
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2