16

重複の可能性:
パフォーマンスが重要な場合は、JavaのString.format()を使用する必要がありますか?

String.format代わりにJavaアプリで使用するのが良いかどうか疑問に思っていStringBuilderたので、次のような簡単なテストを作成します。

public static void main(String[] args) {
        int i = 0;
        Long start = System.currentTimeMillis();
        while (i < 10000) {
            String s = String.format("test %d", i);
            i++;
        }
        System.out.println(System.currentTimeMillis() - start);
        i = 0;
        start = System.currentTimeMillis();
        while (i < 10000) {
            String s = new StringBuilder().append("test ").append(i).toString();
            i++;
        }
        System.out.println(System.currentTimeMillis() - start);
    }

そして、結果は次のとおりです。

238
15

したがって、私のテストが有効である場合は、StringBuilderよりも高速ですString.format。わかった。今、私はどのように機能するかを考え始めますString.format。これは、次のような単純な文字列連結"test " + iですか?

StringBuilder連結との違いは何String.formatですか?のように単純String.formatで速い方法はありStringBuilderますか?

4

3 に答える 3

38

、、、正規作用素、およびメソッドと比較するための簡単なキャリパーベンチマークを作成しました。String.format()StringBuilderStringBufferString +String.replace()String.concat()

public class StringFormatBenchmark extends SimpleBenchmark {

    public void timeStringFormat(int reps) {
        while (--reps >= 0) {
            String s = String.format("test %d", reps);
        }
    }

    public void timeStringBuilder(int reps) {
        while (--reps >= 0) {
            String s = new StringBuilder("test ").append(reps).toString();
        }
    }

    public void timeStringBuffer(int reps) {
        while (--reps >= 0) {
            String s = new StringBuffer("test ").append(reps).toString();
        }
    }

    public void timeStringPlusOperator(int reps) {
        while (--reps >= 0) {
            String s = "test " + reps;
        }
    }

    public void timeReplace(int reps) {
        while (--reps >= 0) {
            String s = "test {}".replace("{}", String.valueOf(reps));
        }
    }

    public void timeStringConcat(int reps) {
        while (--reps >= 0) {
            String s = "test ".concat(String.valueOf(reps));
        }
    }

    public static void main(String[] args) {
        new Runner().run(StringFormatBenchmark.class.getName());
    }

}

結果は次のとおりです(Java 1.6.0_26-b03、Ubuntu、32ビット):

caliper2

明らかString.format()にはるかに遅いです(桁違いに)。また、 (私たちが教えられたように)StringBufferよりもかなり遅いです。StringBuilder最後にStringBuilderString +演算子は非常によく似たバイトコードにコンパイルされるため、ほとんど同じです。String.concat()少し遅いです。

String.replace()また、単純な連結で十分な場合は使用しないでください。

于 2012-10-08T18:05:53.567 に答える
3

String.formatは比較的低速ですが、通常は十分に高速です。

アプリケーションのプロファイルを作成するときにパフォーマンスの問題が見られない限り、それがより単純な場合はフォーマットを使用します。

注:この例のString.formatは、最大24マイクロ秒かかり、まだ完全にウォームアップされていません。最初の10K回の反復は無視します。

この場合、 IMHO"test " + iが最も単純です。

于 2012-10-08T17:53:54.590 に答える
1

(メソッドがコンパイルされた後)JVMウォームアップ後にテストを実行し、同様の結果を取得しました。StringBuilderの方が30倍以上高速です。

フォーマット:943
stringbuilder:26

public class TestPerf {

    private static int NUM_RUN;


    public static void main(String[] args) {
        NUM_RUN = 100_000;
        //warm up
        for (int i = 0; i < 10; i++) {
            method1();
            method2();
        }

        System.gc();
        System.out.println("Starting");

        long sum = 0;
        long start = System.nanoTime();
        for (int i = 0; i < 10; i++) {
            sum += method1();
        }
        long end = System.nanoTime();
        System.out.println("format: " + (end - start) / 1000000);

        System.gc();

        start = System.nanoTime();
        for (int i = 0; i < 10; i++) {
            sum += method2();
        }
        end = System.nanoTime();
        System.out.println("stringbuilder: " + (end - start) / 1000000);

        System.out.println(sum);
    }

    private static int method1() {
        int sum = 0;
        for (int i = 0; i < NUM_RUN; i++) {
            String s = String.format("test %d", i);
            sum += s.length();
        }
        return sum;
    }

    private static int method2() {
        int sum = 0;
        for (int i = 0; i < NUM_RUN; i++) {
            String s = new StringBuilder().append("test ").append(i).toString();
            sum += s.length();
        }
        return sum;
    }
}
于 2012-10-08T18:00:14.500 に答える