String
を連結するには、StringBuilder
+ String
の代わりにString
を使用することがよくありますが、書式設定された値を返すString.format
でも同じことができます指定されたロケール、フォーマット、および引数による文字列。
例:
StringBuilderと文字列を連結します
String concatenateStringWithStringBuilder(String name, String lName, String nick) {
final StringBuilder sb = new StringBuilder("Contact {");
sb.append(", name='").append(name)
.append(", lastName='").append(lName)
.append(", nickName='").append(nick)
.append('}');
return sb.toString();
}
StringFormat:で文字列を連結します
String concatenateStringWithStringFormat(String name, String lName, String nick) {
return String.format("Contact {name=%s, lastName=%s, nickName=%s}", name, lName, nick);
}
パフォーマンスでは、String.Format
はStringBuilder
と同じくらい効率的ですか?文字列を連結する方が良いのはなぜですか?
[〜#〜] update [〜#〜]
同様の question をチェックしましたが、質問には答えていません。これまで、文字列を連結するためにStringBuilder
を使用しました。または、String.format
を使用する必要がありますか?問題は、どちらが優れているか、なぜですか?
StringBuilder
vs String.format
で少しテストを行った後、それぞれが連結を解決するのにどれくらいの時間がかかるかがわかりました。ここにスニペットコードと結果
コード:
String name = "stackover";
String lName = " flow";
String nick = " stackoverflow";
String email = "[email protected]";
int phone = 123123123;
//for (int i = 0; i < 10; i++) {
long initialTime1 = System.currentTimeMillis();
String response = String.format(" - Contact {name=%s, lastName=%s, nickName=%s, email=%s, phone=%d}",
name, lName, nick, email, phone);
long finalTime1 = System.currentTimeMillis();
long totalTime1 = finalTime1 - initialTime1;
System.out.println(totalTime1 + response);
long initialTime2 = System.currentTimeMillis();
final StringBuilder sb = new StringBuilder(" - Contact {");
sb.append("name=").append(name)
.append(", lastName=").append(lName)
.append(", nickName=").append(nick)
.append(", email=").append(email)
.append(", phone=").append(phone)
.append('}');
String response2 = sb.toString();
long finalTime2 = System.currentTimeMillis();
long totalTime2 = finalTime2 - initialTime2;
System.out.println(totalTime2 + response2);
//}
コードを数回実行した後、String.format
に時間がかかることがわかりました。
String.format: 46: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
String.format: 38: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
String.format: 51: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
しかし、ループ内で同じコードを実行すると、結果が変わります。
String.format: 43: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, [email protected], phone=123123123}
String.format
の最初の実行には時間がかかります。その後、StringBuilder
の結果として一定にならなくても時間が短くなります
@ G.Fiedlerが言ったように:「String.format
はフォーマット文字列を解析する必要があります...」
これらの結果から、StringBuilder
はString.format
よりも効率的であると言えます。
「より良い」ものは、単にあなたの要件に依存します:
たとえば_String Builder
_は高速ですが、コードははるかに読みにくくなり、間違いを犯しやすくなります。
一方、String.format()
はパフォーマンスを犠牲にしてより読みやすいコードを生成します。
パフォーマンスの違いを示すJMHベンチマーク(文字列ビルダーコードが長く、結果の文字列がどのように見えるかを理解するのが非常に難しいことに注意してください):
_@Fork(1)
@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Measurement(iterations = 10)
@Warmup(iterations = 10)
@BenchmarkMode(Mode.Throughput)
public class StringFormatBenchmark {
private String name = "UserName";
private String lName = "LUserName";
private String nick = "UserNick";
@Benchmark
public void stringFormat(Blackhole blackhole) {
final String result = String.format("Contact {name=%s, lastName=%s, nickName=%s}", name, lName, nick);
blackhole.consume(result);
}
@Benchmark
public void stringBuilder(Blackhole blackhole) {
final StringBuffer sb = new StringBuffer("Contact {");
sb.append(", name='").append(name)
.append(", lastName='").append(lName)
.append(", nickName='").append(nick)
.append('}');
final String result = sb.toString();
blackhole.consume(result);
}
}
_
そして結果:
_Benchmark Mode Cnt Score Error Units
StringFormatBenchmark.stringBuilder thrpt 10 10617.210 ± 157.302 ops/ms
StringFormatBenchmark.stringFormat thrpt 10 960.658 ± 7.398 ops/ms
_
パフォーマンスが重要でないコードの場合は、String.format()
を使用することをお勧めします。使用が簡単で快適だからです。また、パターンを見るだけで、結果の文字列がどのように見えるかがわかります。パフォーマンスが重要なコードを実行している場合、またはGCへの影響を小さくする必要がある場合は、StringBuilder
を使用します。これは、高速で再利用できるためです。
StringBuilder
は、String.format
は、フォーマット文字列(複雑なドメイン固有の言語)を解析する必要があります。そしてそれは高価です。
String + Stringの代わりにStringBuilder
ところで:同じバイトコードになるので同じです(Java 1.5)。