web-dev-qa-db-ja.com

String.format()と「+」演算子

基本的な文字列連結操作には何を使用する必要がありますか?

_String randomString = "hello " + userName + " how are you" ?
_

または

_String randomString = String.format("hello %s how are you ?",userName);
_

私はString.format()が出力文字列のより良いアイデアを与えると感じています。しかし、実際にどれがpro and consのどれを使用するのですか?

文字列リテラルプールのパフォーマンスや孤立エントリに関して何かありますか。

編集:1つだけでなく、文字列内の複数のパラメータについて話している。約5 +。

ボーナス質問:実際にどのように使用すべきかについての意見も教えてください。これらのいずれかまたは3番目の1つ... !! ?

23
Priyank Doshi

パフォーマンスのみを求めている場合、StringBuilder/StringBufferを使用するのが文字列を作成する最も効率的な方法だと思います。 Javaコンパイラは、ほとんどの文字列連結をStringBuilder同等のものに変換できるほどスマートです。

読みやすさを求めている場合は、String.formatの方がはるかに明確だと思います。これは、高いパフォーマンスに依存する必要がない限り、私が使用するものでもあります。

したがって、主な関心事がパフォーマンスではない場合、つまりこのコードが頻繁に呼び出されるパスにない場合は、String.formatを使用することをお勧めします。これにより、結果として得られる文字列がよくわかります(前述のとおり)。

また、String.formatを使用すると、フォーマットを使用できます。つまり、文字列のパディング、数値、日付のフォーマットなどに使用できるため、単純な連結を使用するとコードがさらに悪化します。

編集チュウ

[〜#〜] jad [〜#〜] を使用すると、次のコードを確認できます。

public class Test {
    public static void main(String[] args) {
        String str = "a" + "b" + "c";
        String str2 = "foo" + str + "bar" + str;
        System.out.println(str2);
    }
}

逆コンパイルすると、次のようになります。

public class Test {
    public static void main(String[] args) {
        String str = "abc";
        String str2 = new StringBuilder("foo").append(str).append("bar").append(str).toString();
        System.out.println(str2);
    }
}

その証明はjavapユーティリティを使用して見つけることもできます。これは.classファイルの下にJavaバイトコードを表示します:

public static void main(Java.lang.String[] args);
    0  ldc <String "abc"> [16]
    2  astore_1 [str]
    3  new Java.lang.StringBuilder [18]
    6  dup
    7  ldc <String "foo"> [20]
    9  invokespecial Java.lang.StringBuilder(Java.lang.String) [22]
   12  aload_1 [str]
   13  invokevirtual Java.lang.StringBuilder.append(Java.lang.String) : Java.lang.StringBuilder [25]
   16  ldc <String "bar"> [29]
   18  invokevirtual Java.lang.StringBuilder.append(Java.lang.String) : Java.lang.StringBuilder [25]
   21  aload_1 [str]
   22  invokevirtual Java.lang.StringBuilder.append(Java.lang.String) : Java.lang.StringBuilder [25]
   25  invokevirtual Java.lang.StringBuilder.toString() : Java.lang.String [31]
   28  astore_2 [str2]
   29  getstatic Java.lang.System.out : Java.io.PrintStream [35]
   32  aload_2 [str2]
   33  invokevirtual Java.io.PrintStream.println(Java.lang.String) : void [41]
   36  return
24
Alex

基本的な文字列連結操作には何を使用する必要がありますか?

提供する例は、サーバーの目的が異なります。 +Stringsを連結するためにオーバーロードされますが、String.formatは名前が指定するように文字列をフォーマットするために使用されます。

文字列を連結することは、主な仕事ではありません。

したがって、単に連結する必要がある場合は、+または concat メソッドを使用します。

これらのリンクは役に立ちます:

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

Javaで文字列連結よりもString.formatを使用する方が良いでしょうか?

8
Azodious

これを試して

    long t0 = System.currentTimeMillis();
        String userName = "test";
        for (int i = 0; i < 1000000; i++) {
            String randomString = "hello " + userName + " how are you?";
//          String randomString = String.format("hello %s how are you ?",userName);
        }
        System.out.println(System.currentTimeMillis() - t0);

連結はString.formatよりも10倍速いことに驚かれるでしょう。しかし、formatは数値や日付など、非常に便利なことがたくさんあります。詳細については、String.formatで実際に使用されているJava.util.Formatter APIを参照してください。

3

私の意見では、_+ operator_を使用します。

パフォーマンスが気になる場合は、StringBuilderを使用する必要があります。上記のコメントでAlexが指摘したように、Javaコンパイラーは次のように変換します。

_String str2 = "a" + str1;_

へ:String str2 = new StringBuilder("a").append(str1)).toString();

これに加えて、_+ operator_を使用してランタイム例外を回避できます。代わりに、コンパイル時に捕捉できる構文エラーが発生します。例えば:

_    String var = "huge success.";

    System.out.print( "I'm making a note here: " + var );
    //System.out.print( "Printing: " + ); Syntax error!

    System.out.print( String.format( "I'm making a note here: '%s'", var ) );
    System.out.print( String.format( "I'm making a note here: '%s'" ) ); // runtime exception!
    System.out.print( String.format( "I'm making a note here: '%d'", var ) ); // runtime exception!
_

読みやすさは個人の好みに依存します。ただし、私は_String.format_構文は基本的にC++からのものであり、それ以降、ほとんどの言語は読みやすさの理由で_+ operator_を採用しています。

2
rhinoinrepose

私の2セント:常にString.format()を使用します

この状況では、国際化はスタイルやパフォーマンスよりもはるかに大きな懸念事項です。そのため、常にString.format()を使用します

英語のテキスト:"Hello " + userName + " how are you?"

ジェダイへの翻訳:userName + "you are how? Hello!"

文字列が連結されている場合、翻訳者にとって不可能ではないにしても、Wordの順序を変更することは困難です。この問題は、文字列へのピースの数とプレースホルダーの数が増えるにつれて、ますます悪化します。

2
njr101

StringBufferの使用を推奨するほとんどの人は過去に生きています。現在のベストプラクティスは、StringBuilderを使用することです。しかし、これは変わる可能性があるので、コンパイラにそれを行わせてみませんか? "+"だけを使用すると、コンパイラは現在の実装を選択します。これにより、静的文字列を組み合わせることができます( "foo" + "bar"は単一の "foobar"になります)。

StringBuilderを明示的に割り当てる唯一の場所はループです(ループの前に作成され、その中で使用されます)。

何が起きているかわからない場合は、生成されたバイトコードを確認してください。

では、いつフォーマットを使用するのですか?実際のformattingが複雑な場合は、formatを使用します。しかし、あなたは今、単純な連結について話している。

1
Fabian Lange

個人的には、見た目がよく、パフォーマンスに大きな影響を与えるとは思えないため、フォーマットを使用したいと思います。

1
Duane

次のような利点があるため、String.Formatの方が効率的です。

  1. 読みやすさの向上
  2. より良い翻訳可能
  3. 書式文字列では、書式プロバイダーと単純な書式インジケーター(固定幅など)を直接使用できます。
  4. 構成ファイルにフォーマット文字列を入れることで、いくつかの強力なことができます。
  5. String.Format()は、背後でStringBuilderと効率的なステートマシンを使用するため、多くの場合より高速ですが、.Netでの文字列連結は比較的低速です。これは、文字列のサイズと置換された値の数が増えると特に当てはまります。

ありがとう。

1
Chetan S

String.formatに関する私の主な懸念は、それがロケール固有の操作であり、コードが別のロケールで実行された場合、予期しない結果になる可能性があることです。

そのコンパクトな構文は本当に素晴らしいので、ロケール以外の代替手段を用意したいと思います。

0