簡體   English   中英

String.format和StringBuilder之間的性能

[英]Performance between String.format and StringBuilder

為了連接String我們經常使用StringBuilder而不是String + String ,但我們也可以使用String.format執行相同的操作, 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.FormatStringBuilder一樣高效嗎? 哪一個更好地連接字符串,為什么?

UPDATE

我檢查了類似的問題 ,但沒有回答我的問題。 到目前為止,我已經使用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必須解析格式字符串(一種復雜的域特定語言)。 那很貴。

StringBuilder而不是String + String

BTW:它是一樣的,因為它產生相同的字節代碼(從Java 1.5開始)。

在使用StringBuilderString.format進行一些測試之后,我了解了每個解決連接所花費的時間。 這里是代碼段和結果

碼:

String name = "stackover";
String lName = " flow";
String nick = " stackoverflow";
String email = "stackoverflow@email.com";
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=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 38: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 51: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}

但是如果我在循環中運行相同的代碼,結果會發生變化。

String.format: 43: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
String.format: 1: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}
StringBuilder: 0: Contact {name=stackover, lastName= flow, nickName= stackoverflow, email=stackoverflow@email.com, phone=123123123}

String.format第一次運行它需要更多的時間,之后時間更短,即使它不會因StringBuilder而變得不變

正如@ G.Fiedler所說:“ String.format必須解析格式字符串......”

有了這些結果,可以說StringBuilderString.format更有效

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM