314

String.formatJavaでの文字列連結の使用と文字列連結の間に認識できる違いはありますか?

私は使用する傾向がありますString.formatが、ときどきスリップして連結を使用します。どちらがもう一方よりも優れているのだろうかと思っていました。

私の見方ではString.format、文字列を「フォーマット」する際により強力になります。連結とは、誤って余分な%sを入力したり、欠落したりすることを心配する必要がないことを意味します。

String.formatまた短いです。

どちらが読みやすいかは、頭がどのように機能するかによって異なります。

4

14 に答える 14

270

を使用することをお勧めしますString.format()。主な理由は、String.format()リソース ファイルから読み込まれたテキストを使用してローカライズする方が簡単であるのに対し、言語ごとに異なるコードを使用して新しい実行可能ファイルを作成しないと連結をローカライズできないためです。

アプリをローカライズ可能にする予定がある場合は、フォーマット トークンにも引数の位置を指定する習慣を身に付ける必要があります。

"Hello %1$s the time is %2$t"

次に、これをローカライズして、異なる順序を考慮して実行可能ファイルを再コンパイルすることなく、名前と時刻のトークンを交換できます。引数の位置を使用すると、同じ引数を関数に 2 回渡すことなく再利用することもできます。

String.format("Hello %1$s, your name is %1$s and the time is %2$t", name, time)
于 2009-05-29T10:56:34.363 に答える
206

性能について:

public static void main(String[] args) throws Exception {      
  long start = System.currentTimeMillis();
  for(int i = 0; i < 1000000; i++){
    String s = "Hi " + i + "; Hi to you " + i*2;
  }
  long end = System.currentTimeMillis();
  System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;

  start = System.currentTimeMillis();
  for(int i = 0; i < 1000000; i++){
    String s = String.format("Hi %s; Hi to you %s",i, + i*2);
  }
  end = System.currentTimeMillis();
  System.out.println("Format = " + ((end - start)) + " millisecond");
}

タイミングの結果は次のとおりです。

  • 連結 = 265 ミリ秒
  • フォーマット = 4141 ミリ秒

したがって、連結は String.format よりもはるかに高速です。

于 2010-01-18T16:58:06.277 に答える
46

問題の 1 つ.formatは、静的型の安全性が失われることです。フォーマットの引数が少なすぎる可能性があり、フォーマット指定子の型が間違っている可能性があります - どちらもIllegalFormatException at runtimeにつながるため、本番環境を壊すログ コードになる可能性があります。

対照的に、への引数+はコンパイラでテストできます。

(関数がモデル化されている) セキュリティの歴史は長く、恐ろしいものです。format

于 2012-02-23T14:56:30.603 に答える
41

パフォーマンスについての議論があるので、StringBuilder を含む比較を追加することにしました。実際、concat よりも高速であり、当然 String.format オプションよりも高速です。

これを一種のリンゴとリンゴの比較にするために、新しい StringBuilder を外側ではなくループ内でインスタンス化します (これは、ループの最後に追加するループ用のスペースを再割り当てするオーバーヘッドが原因で、インスタンス化を 1 回だけ行うよりも実際には高速です)。一人のビルダー)。

    String formatString = "Hi %s; Hi to you %s";

    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = String.format(formatString, i, +i * 2);
    }

    long end = System.currentTimeMillis();
    log.info("Format = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        String s = "Hi " + i + "; Hi to you " + i * 2;
    }

    end = System.currentTimeMillis();

    log.info("Concatenation = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        StringBuilder bldString = new StringBuilder("Hi ");
        bldString.append(i).append("; Hi to you ").append(i * 2);
    }

    end = System.currentTimeMillis();

    log.info("String Builder = " + ((end - start)) + " millisecond");
  • 2012-01-11 16:30:46,058 INFO [TestMain] - フォーマット = 1416 ミリ秒
  • 2012-01-11 16:30:46,190 INFO [TestMain] - 連結 = 134 ミリ秒
  • 2012-01-11 16:30:46,313 INFO [TestMain] - 文字列ビルダー = 117 ミリ秒
于 2012-01-11T22:47:02.910 に答える
24

どちらが読みやすいかは、頭の働き次第です。

あなたはすぐに答えを得ました。

それは個人的な好みの問題です。

文字列の連結はわずかに高速だと思いますが、それは無視できるはずです。

于 2009-05-29T10:56:49.527 に答える
19

これは、ミリ秒単位で複数のサンプル サイズを使用したテストです。

public class Time {

public static String sysFile = "/sys/class/camera/rear/rear_flash";
public static String cmdString = "echo %s > " + sysFile;

public static void main(String[] args) {

  int i = 1;
  for(int run=1; run <= 12; run++){
      for(int test =1; test <= 2 ; test++){
        System.out.println(
                String.format("\nTEST: %s, RUN: %s, Iterations: %s",run,test,i));
        test(run, i);
      }
      System.out.println("\n____________________________");
      i = i*3;
  }
}

public static void test(int run, int iterations){

      long start = System.nanoTime();
      for( int i=0;i<iterations; i++){
          String s = "echo " + i + " > "+ sysFile;
      }
      long t = System.nanoTime() - start;   
      String r = String.format("  %-13s =%10d %s", "Concatenation",t,"nanosecond");
      System.out.println(r) ;


     start = System.nanoTime();       
     for( int i=0;i<iterations; i++){
         String s =  String.format(cmdString, i);
     }
     t = System.nanoTime() - start; 
     r = String.format("  %-13s =%10d %s", "Format",t,"nanosecond");
     System.out.println(r);

      start = System.nanoTime();          
      for( int i=0;i<iterations; i++){
          StringBuilder b = new StringBuilder("echo ");
          b.append(i).append(" > ").append(sysFile);
          String s = b.toString();
      }
     t = System.nanoTime() - start; 
     r = String.format("  %-13s =%10d %s", "StringBuilder",t,"nanosecond");
     System.out.println(r);
}

}

TEST: 1, RUN: 1, Iterations: 1
  Concatenation =     14911 nanosecond
  Format        =     45026 nanosecond
  StringBuilder =      3509 nanosecond

TEST: 1, RUN: 2, Iterations: 1
  Concatenation =      3509 nanosecond
  Format        =     38594 nanosecond
  StringBuilder =      3509 nanosecond

____________________________

TEST: 2, RUN: 1, Iterations: 3
  Concatenation =      8479 nanosecond
  Format        =     94438 nanosecond
  StringBuilder =      5263 nanosecond

TEST: 2, RUN: 2, Iterations: 3
  Concatenation =      4970 nanosecond
  Format        =     92976 nanosecond
  StringBuilder =      5848 nanosecond

____________________________

TEST: 3, RUN: 1, Iterations: 9
  Concatenation =     11403 nanosecond
  Format        =    287115 nanosecond
  StringBuilder =     14326 nanosecond

TEST: 3, RUN: 2, Iterations: 9
  Concatenation =     12280 nanosecond
  Format        =    209051 nanosecond
  StringBuilder =     11818 nanosecond

____________________________

TEST: 5, RUN: 1, Iterations: 81
  Concatenation =     54383 nanosecond
  Format        =   1503113 nanosecond
  StringBuilder =     40056 nanosecond

TEST: 5, RUN: 2, Iterations: 81
  Concatenation =     44149 nanosecond
  Format        =   1264241 nanosecond
  StringBuilder =     34208 nanosecond

____________________________

TEST: 6, RUN: 1, Iterations: 243
  Concatenation =     76018 nanosecond
  Format        =   3210891 nanosecond
  StringBuilder =     76603 nanosecond

TEST: 6, RUN: 2, Iterations: 243
  Concatenation =     91222 nanosecond
  Format        =   2716773 nanosecond
  StringBuilder =     73972 nanosecond

____________________________

TEST: 8, RUN: 1, Iterations: 2187
  Concatenation =    527450 nanosecond
  Format        =  10291108 nanosecond
  StringBuilder =    885027 nanosecond

TEST: 8, RUN: 2, Iterations: 2187
  Concatenation =    526865 nanosecond
  Format        =   6294307 nanosecond
  StringBuilder =    591773 nanosecond

____________________________

TEST: 10, RUN: 1, Iterations: 19683
  Concatenation =   4592961 nanosecond
  Format        =  60114307 nanosecond
  StringBuilder =   2129387 nanosecond

TEST: 10, RUN: 2, Iterations: 19683
  Concatenation =   1850166 nanosecond
  Format        =  35940524 nanosecond
  StringBuilder =   1885544 nanosecond

  ____________________________

TEST: 12, RUN: 1, Iterations: 177147
  Concatenation =  26847286 nanosecond
  Format        = 126332877 nanosecond
  StringBuilder =  17578914 nanosecond

TEST: 12, RUN: 2, Iterations: 177147
  Concatenation =  24405056 nanosecond
  Format        = 129707207 nanosecond
  StringBuilder =  12253840 nanosecond
于 2014-10-22T07:06:41.973 に答える
10

これは、 StringBuilderでtoString()メソッドを呼び出すことを変更した、上記と同じテストです。以下の結果は、StringBuilder アプローチが+演算子を使用した文字列連結よりも少しだけ遅いことを示しています。

ファイル: StringTest.java

class StringTest {

  public static void main(String[] args) {

    String formatString = "Hi %s; Hi to you %s";

    long start = System.currentTimeMillis();
    for (int i = 0; i < 1000000; i++) {
        String s = String.format(formatString, i, +i * 2);
    }

    long end = System.currentTimeMillis();
    System.out.println("Format = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        String s = "Hi " + i + "; Hi to you " + i * 2;
    }

    end = System.currentTimeMillis();

    System.out.println("Concatenation = " + ((end - start)) + " millisecond");

    start = System.currentTimeMillis();

    for (int i = 0; i < 1000000; i++) {
        StringBuilder bldString = new StringBuilder("Hi ");
        bldString.append(i).append("Hi to you ").append(i * 2).toString();
    }

    end = System.currentTimeMillis();

    System.out.println("String Builder = " + ((end - start)) + " millisecond");

  }
}

シェル コマンド : (コンパイルして StringTest を 5 回実行)

> javac StringTest.java
> sh -c "for i in \$(seq 1 5); do echo \"Run \${i}\"; java StringTest; done"

結果 :

Run 1
Format = 1290 millisecond
Concatenation = 115 millisecond
String Builder = 130 millisecond

Run 2
Format = 1265 millisecond
Concatenation = 114 millisecond
String Builder = 126 millisecond

Run 3
Format = 1303 millisecond
Concatenation = 114 millisecond
String Builder = 127 millisecond

Run 4
Format = 1297 millisecond
Concatenation = 114 millisecond
String Builder = 127 millisecond

Run 5
Format = 1270 millisecond
Concatenation = 114 millisecond
String Builder = 126 millisecond
于 2013-12-03T21:29:33.153 に答える
7

String.format()文字列を連結するだけではありません。たとえば、 を使用して特定のロケールで数値を表示できますString.format()

ただし、ローカリゼーションを気にしないのであれば、機能的な違いはありません。たぶん、一方が他方より速いかもしれませんが、ほとんどの場合、無視できます..

于 2009-05-29T11:01:19.410 に答える
6

一般に、文字列連結は より優先されるべきString.formatです。後者には 2 つの主な欠点があります。

  1. ローカルで構築される文字列をエンコードしません。
  2. 構築プロセスは文字列にエンコードされます。

String.format()ポイント 1 とは、呼び出しが 1 回の連続パスで何を行っているかを理解できないことを意味します。引数の位置を数えながら、フォーマット文字列と引数の間を行ったり来たりする必要があります。短い連結の場合、これはあまり問題になりません。ただし、これらの場合、文字列の連結は冗長ではありません。

ポイント 2 は、構築プロセスの重要な部分が(DSL を使用して)フォーマット文字列にエンコードされていることを意味します。文字列を使用してコードを表すことには、多くの欠点があります。本質的にタイプ セーフではなく、構文の強調表示、コード分析、最適化などを複雑にします。

もちろん、Java 言語以外のツールやフレームワークを使用する場合、新しい要因が発生する可能性があります。

于 2016-01-02T13:41:12.073 に答える
2

特定のベンチマークは行っていませんが、連結の方が速いと思います。String.format() は新しい Formatter を作成し、これが新しい StringBuilder (サイズはわずか 16 文字) を作成します。これは、特に長い文字列をフォーマットし、StringBuilder のサイズを変更し続ける場合に、かなりのオーバーヘッドになります。

ただし、連結はあまり役に立たず、読みにくくなります。いつものように、コードのベンチマークを実行して、どちらが優れているかを確認する価値があります。リソース バンドル、ロケールなどがメモリに読み込まれ、コードが JIT された後、サーバー アプリでの違いは無視できる場合があります。

おそらくベスト プラクティスとして、適切なサイズの StringBuilder (追加可能) と Locale を使用して独自の Formatter を作成し、多くの書式設定を行う必要がある場合はそれを使用することをお勧めします。

于 2009-05-29T14:55:43.383 に答える
2

目に見える違いがあるかもしれません。

String.formatは非常に複雑で、その下で正規表現を使用しているため、どこでも使用するのを習慣にしないでください。必要な場所だけに使用してください。

StringBuilder桁違いに高速になります(ここの誰かがすでに指摘しているように)。

于 2011-10-04T23:58:36.507 に答える
-1

上記のプログラムでは、String Concatenation と String.Format を比較することはできません。

以下のように、コードブロックで String.Format と Concatenation を使用する位置を交換することもできます。

public static void main(String[] args) throws Exception {      
  long start = System.currentTimeMillis();

  for( int i=0;i<1000000; i++){
    String s = String.format( "Hi %s; Hi to you %s",i, + i*2);
  }

  long end = System.currentTimeMillis();
  System.out.println("Format = " + ((end - start)) + " millisecond");
  start = System.currentTimeMillis();

  for( int i=0;i<1000000; i++){
    String s = "Hi " + i + "; Hi to you " + i*2;
  }

  end = System.currentTimeMillis();
  System.out.println("Concatenation = " + ((end - start)) + " millisecond") ;
}

ここで Format がより高速に動作することに驚くでしょう。これは、作成された最初のオブジェクトが解放されない可能性があり、メモリの割り当てに問題が発生してパフォーマンスが低下する可能性があるためです。

于 2011-09-28T04:44:46.217 に答える