基本的な文字列連結操作には何を使用する必要がありますか?
_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つ... !! ?
パフォーマンスのみを求めている場合、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
基本的な文字列連結操作には何を使用する必要がありますか?
提供する例は、サーバーの目的が異なります。 +
はString
sを連結するためにオーバーロードされますが、String.format
は名前が指定するように文字列をフォーマットするために使用されます。
文字列を連結することは、主な仕事ではありません。
したがって、単に連結する必要がある場合は、+
または concat メソッドを使用します。
これらのリンクは役に立ちます:
これを試して
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を参照してください。
私の意見では、_+ 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セント:常にString.format()
を使用します
この状況では、国際化はスタイルやパフォーマンスよりもはるかに大きな懸念事項です。そのため、常にString.format()
を使用します
英語のテキスト:"Hello " + userName + " how are you?"
ジェダイへの翻訳:userName + "you are how? Hello!"
文字列が連結されている場合、翻訳者にとって不可能ではないにしても、Wordの順序を変更することは困難です。この問題は、文字列へのピースの数とプレースホルダーの数が増えるにつれて、ますます悪化します。
StringBufferの使用を推奨するほとんどの人は過去に生きています。現在のベストプラクティスは、StringBuilderを使用することです。しかし、これは変わる可能性があるので、コンパイラにそれを行わせてみませんか? "+"だけを使用すると、コンパイラは現在の実装を選択します。これにより、静的文字列を組み合わせることができます( "foo" + "bar"は単一の "foobar"になります)。
StringBuilderを明示的に割り当てる唯一の場所はループです(ループの前に作成され、その中で使用されます)。
何が起きているかわからない場合は、生成されたバイトコードを確認してください。
では、いつフォーマットを使用するのですか?実際のformattingが複雑な場合は、formatを使用します。しかし、あなたは今、単純な連結について話している。
個人的には、見た目がよく、パフォーマンスに大きな影響を与えるとは思えないため、フォーマットを使用したいと思います。
次のような利点があるため、String.Formatの方が効率的です。
ありがとう。
String.format
に関する私の主な懸念は、それがロケール固有の操作であり、コードが別のロケールで実行された場合、予期しない結果になる可能性があることです。
そのコンパクトな構文は本当に素晴らしいので、ロケール以外の代替手段を用意したいと思います。