java字符连接字符串数组_Java中连接字符串的最佳方法
java字符連接字符串數組
最近有人問我這個問題–在Java中使用+運算符連接字符串是否對性能不利?
這讓我開始思考Java中連接字符串的不同方法,以及它們如何相互對抗。 這些是我要研究的方法:
我還嘗試了String.format()但是它是如此緩慢,以至于我暫時不在本文中介紹。
在繼續(xù)之前,我們應該分離兩個用例:
我最初的想法和問題如下:
我要解決的第一個問題是+運算符的工作方式。 我一直都知道它在幕后使用了StringBuilder,但是要證明這一點,我們需要檢查字節(jié)碼。
如今 ,查看字節(jié)碼最簡單的方法是使用JITWatch ,這是一個非常出色的工具,旨在了解JIT如何編譯您的代碼。 它有一個很棒的視圖,您可以在其中與字節(jié)碼(如果要轉到該級別,還可以是機器碼)并排查看源代碼。
這是一個非常簡單的方法plus2()的字節(jié)碼,我們可以看到確實在第6行上創(chuàng)建了一個StringBuilder,并附加了變量a(第14行)和b(第18行)。
我認為將其與StringBuffer的手工使用進行比較會很有趣,因此我創(chuàng)建了另一個方法build2(),結果如下。
此處生成的字節(jié)碼不如plus()方法那么緊湊。 StringBuilder存儲在變量高速緩存中(第13行),而不是僅留在堆棧上。 我不知道為什么會這樣,但是JIT也許可以做到這一點,我們將不得不看看時機如何。
無論如何,如果用plus運算符和StringBuilder將2個字符串連接在一起的結果顯著不同,那將是非常令人驚訝的。
我寫了一個小型的JMH測試來確定不同方法的執(zhí)行方式。 首先讓我們看一下兩個Strings測試。 參見下面的代碼:
package org.sample;import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.infra.Blackhole;import java.util.UUID; import java.util.concurrent.TimeUnit;@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Fork(1) @State(Scope.Thread) public class LoopStringsBenchmark {private String[] strings;@Setuppublic void setupTest(){strings = new String[100];for(int i = 0; i<100; i++) {strings[i] = UUID.randomUUID().toString().substring(0, 10);}}@Benchmarkpublic void testPlus(Blackhole bh) {String combined = "";for(String s : strings) {combined = combined + s;}bh.consume(combined);}@Benchmarkpublic void testStringBuilder(Blackhole bh) {StringBuilder sb = new StringBuilder();for(String s : strings) {sb.append(s);}bh.consume(sb.toString());}@Benchmarkpublic void testStringBuffer(Blackhole bh) {StringBuffer sb = new StringBuffer();for(String s : strings) {sb.append(s);}bh.consume(sb.toString());}@Benchmarkpublic void testStringJoiner(Blackhole bh) {bh.consume(String.join("", strings));}@Benchmarkpublic void testStringConcat(Blackhole bh) {String combined = "";for(String s : strings) {combined.concat(s);}bh.consume(combined);} }結果如下:
顯而易見的贏家是String.concat()。 毫不奇怪,因為它不必為每次調用創(chuàng)建StringBuilder / StringBuffer而付出性能損失。 雖然確實需要每次都創(chuàng)建一個新的String(這將在以后變得很重要),但是對于連接兩個Sting的非常簡單的情況,它更快。
另一點是,盡管產生了額外的字節(jié)碼,但正如我們預期的那樣,plus和StringBuilder是等效的。 StringBuffer僅比StringBuilder慢一點,這很有趣,這表明JIT必須做一些魔術來優(yōu)化同步。
下一個測試將創(chuàng)建一個100個字符串的數組,每個字符串包含10個字符。 基準測試比較了將100個字符串連接在一起的不同方法所花費的時間。 參見下面的代碼:
這次的結果看起來完全不同:
在這里,加號方法確實遭受了損失。 每當您遍歷循環(huán)時,創(chuàng)建StringBuilder的開銷就會減少。 您可以在字節(jié)碼中清楚地看到這一點:
您可以看到每次執(zhí)行循環(huán)時都會創(chuàng)建一個新的StringBuilder(第30行)。 JIT應該發(fā)現這一點并能夠對其進行優(yōu)化是有爭議的,但是事實并非如此,使用+變得非常慢。
同樣,StringBuilder和StringBuffer的性能完全相同,但是這次它們都比String.concat()快。 String.concat()在循環(huán)的每次迭代中創(chuàng)建新的String所付出的代價最終會增加,并且StringBuilder變得更加高效。
給定可以添加到此方法的所有其他功能,String.join()的效果非常好,但是,正如預期的那樣,對于純串聯(lián)而言,它不是最佳選擇。
摘要
如果要在單行代碼中連接字符串,則我將使用+運算符,因為它最易讀,并且對于單個調用而言,性能實際上并不重要。 還要提防String.concat(),因為您幾乎肯定會需要執(zhí)行空值檢查 ,而其他方法則不需要這樣做。
在循環(huán)中連接字符串時,應使用StringBuilder。 您可以使用StringBuffer,但我不一定在所有情況下都信任JIT來像基準測試中那樣高效地優(yōu)化同步。
我的所有結果都是使用JMH取得的,并且都帶有通常的健康警告 。
翻譯自: https://www.javacodegeeks.com/2015/02/optimum-method-concatenate-strings-java.html
java字符連接字符串數組
總結
以上是生活随笔為你收集整理的java字符连接字符串数组_Java中连接字符串的最佳方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 玩耍的近义词 玩耍的近义词有哪些
- 下一篇: 青海简称是什么 青海简称啥呢