1. ホーム

[解決済み】パフォーマンスを重視するならば、JavaのString.format()を使うべき?

2022-04-04 09:03:16

質問

ログ出力などで、常にStringをビルドする必要があります。JDKのバージョンを重ねるうちに、私たちはどのような場合に StringBuffer (多数の追加、スレッドセーフ)と StringBuilder (多数の追加、非スレッドセーフ)。

を使用する際のアドバイスをお願いします。 String.format() ? それとも、パフォーマンスが重要なワンライナーでは、連結にこだわらざるを得ないのでしょうか?

例:醜い旧式。

String s = "What do you get if you multiply " + varSix + " by " + varNine + "?";

vs. 整頓された新しいスタイル (String.format、これはおそらくより遅い)。

String s = String.format("What do you get if you multiply %d by %d?", varSix, varNine);

注:私の具体的な使用例は、私のコード全体にある何百もの「ワンライナー」ログ文字列です。これらはループを伴わないので StringBuilder はヘビー級すぎる。私が興味があるのは String.format() を具体的に説明します。

解決方法は?

この2つのうちどちらの性能が優れているかをテストするために小さなクラスを書いたところ、5〜6倍の差で + が format に勝った。 自分で試してみてください。

import java.io.*;
import java.util.Date;

public class StringTest{

    public static void main( String[] args ){
    int i = 0;
    long prev_time = System.currentTimeMillis();
    long time;

    for( i = 0; i< 100000; i++){
        String s = "Blah" + i + "Blah";
    }
    time = System.currentTimeMillis() - prev_time;

    System.out.println("Time after for loop " + time);

    prev_time = System.currentTimeMillis();
    for( i = 0; i<100000; i++){
        String s = String.format("Blah %d Blah", i);
    }
    time = System.currentTimeMillis() - prev_time;
    System.out.println("Time after for loop " + time);

    }
}

上記を異なるNで実行すると、どちらも線形に動作することがわかりますが String.format は5〜30倍遅くなります。

その理由は、現在の実装では String.format は、まず正規表現で入力を解析し、それからパラメータを入力します。一方、プラスによる連結は、(JITではなく)javacによって最適化され、その際 StringBuilder.append を直接使用します。