日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java字符连接字符串数组_Java中连接字符串的最佳方法

發(fā)布時(shí)間:2023/12/3 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java字符连接字符串数组_Java中连接字符串的最佳方法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

java字符連接字符串?dāng)?shù)組

最近有人問我這個(gè)問題–在Java中使用+運(yùn)算符連接字符串是否對性能不利?

這讓我開始思考Java中連接字符串的不同方法,以及它們?nèi)绾蜗嗷埂?這些是我要研究的方法:

  • 使用+運(yùn)算符
  • 使用StringBuilder
  • 使用StringBuffer
  • 使用String.concat()
  • 使用String.join ( String.join新增功能)
  • 我還嘗試了String.format()但是它是如此緩慢,以至于我暫時(shí)不在本文中介紹。

    在繼續(xù)之前,我們應(yīng)該分離兩個(gè)用例:

  • 將兩個(gè)字符串串聯(lián)在一起作為一個(gè)調(diào)用,例如在日志消息中。 由于這只是一個(gè)電話,您可能會認(rèn)為性能幾乎不是問題,但結(jié)果仍然很有趣,并且可以闡明該主題。
  • 在一個(gè)循環(huán)中連接兩個(gè)字符串。 在這里,性能更是一個(gè)問題,尤其是當(dāng)循環(huán)很大時(shí)。
  • 我最初的想法和問題如下:

  • +運(yùn)算符是用StringBuilder實(shí)現(xiàn)的,因此至少在連接兩個(gè)String的情況下,它應(yīng)產(chǎn)生與StringBuilder類似的結(jié)果。 幕后到底發(fā)生了什么?
  • 在所有類的設(shè)計(jì)目的都是為了連接Strings并取代StringBuffer之后,StringBuilder應(yīng)該是最有效的方法。 但是,與String.concat()相比,創(chuàng)建StringBuilder的開銷是多少?
  • StringBuffer是連接字符串的原始類–不幸的是,其方法是同步的。 確實(shí)不需要同步,隨后它被不同步的StringBuilder代替。 問題是,JIT是否優(yōu)化了同步?
  • String.concat()應(yīng)該適用于2個(gè)字符串,但是在循環(huán)中是否可以正常工作?
  • String.join()比StringBuilder具有更多的功能,如果我們指示它使用空的定界符來連接String,它將如何影響性能?
  • 我要解決的第一個(gè)問題是+運(yùn)算符的工作方式。 我一直都知道它在幕后使用了StringBuilder,但是要證明這一點(diǎn),我們需要檢查字節(jié)碼。

    如今 ,查看字節(jié)碼最簡單的方法是使用JITWatch ,這是一個(gè)非常出色的工具,旨在了解JIT如何編譯您的代碼。 它有一個(gè)很棒的視圖,您可以在其中與字節(jié)碼(如果要轉(zhuǎn)到該級別,還可以是機(jī)器碼)并排查看源代碼。

    這是一個(gè)非常簡單的方法plus2()的字節(jié)碼,我們可以看到確實(shí)在第6行上創(chuàng)建了一個(gè)StringBuilder,并附加了變量a(第14行)和b(第18行)。

    我認(rèn)為將其與StringBuffer的手工使用進(jìn)行比較會很有趣,因此我創(chuàng)建了另一個(gè)方法build2(),結(jié)果如下。

    此處生成的字節(jié)碼不如plus()方法那么緊湊。 StringBuilder存儲在變量高速緩存中(第13行),而不是僅留在堆棧上。 我不知道為什么會這樣,但是JIT也許可以做到這一點(diǎn),我們將不得不看看時(shí)機(jī)如何。

    無論如何,如果用plus運(yùn)算符和StringBuilder將2個(gè)字符串連接在一起的結(jié)果顯著不同,那將是非常令人驚訝的。

    我寫了一個(gè)小型的JMH測試來確定不同方法的執(zhí)行方式。 首先讓我們看一下兩個(gè)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);} }

    結(jié)果如下:

    顯而易見的贏家是String.concat()。 毫不奇怪,因?yàn)樗槐貫槊看握{(diào)用創(chuàng)建StringBuilder / StringBuffer而付出性能損失。 雖然確實(shí)需要每次都創(chuàng)建一個(gè)新的String(這將在以后變得很重要),但是對于連接兩個(gè)Sting的非常簡單的情況,它更快。

    另一點(diǎn)是,盡管產(chǎn)生了額外的字節(jié)碼,但正如我們預(yù)期的那樣,plus和StringBuilder是等效的。 StringBuffer僅比StringBuilder慢一點(diǎn),這很有趣,這表明JIT必須做一些魔術(shù)來優(yōu)化同步。

    下一個(gè)測試將創(chuàng)建一個(gè)100個(gè)字符串的數(shù)組,每個(gè)字符串包含10個(gè)字符。 基準(zhǔn)測試比較了將100個(gè)字符串連接在一起的不同方法所花費(fèi)的時(shí)間。 參見下面的代碼:

    這次的結(jié)果看起來完全不同:

    在這里,加號方法確實(shí)遭受了損失。 每當(dāng)您遍歷循環(huán)時(shí),創(chuàng)建StringBuilder的開銷就會減少。 您可以在字節(jié)碼中清楚地看到這一點(diǎn):

    您可以看到每次執(zhí)行循環(huán)時(shí)都會創(chuàng)建一個(gè)新的StringBuilder(第30行)。 JIT應(yīng)該發(fā)現(xiàn)這一點(diǎn)并能夠?qū)ζ溥M(jìn)行優(yōu)化是有爭議的,但是事實(shí)并非如此,使用+變得非常慢。

    同樣,StringBuilder和StringBuffer的性能完全相同,但是這次它們都比String.concat()快。 String.concat()在循環(huán)的每次迭代中創(chuàng)建新的String所付出的代價(jià)最終會增加,并且StringBuilder變得更加高效。

    給定可以添加到此方法的所有其他功能,String.join()的效果非常好,但是,正如預(yù)期的那樣,對于純串聯(lián)而言,它不是最佳選擇。

    摘要

    如果要在單行代碼中連接字符串,則我將使用+運(yùn)算符,因?yàn)樗钜鬃x,并且對于單個(gè)調(diào)用而言,性能實(shí)際上并不重要。 還要提防String.concat(),因?yàn)槟鷰缀蹩隙〞枰獔?zhí)行空值檢查 ,而其他方法則不需要這樣做。

    在循環(huán)中連接字符串時(shí),應(yīng)使用StringBuilder。 您可以使用StringBuffer,但我不一定在所有情況下都信任JIT來像基準(zhǔn)測試中那樣高效地優(yōu)化同步。

    我的所有結(jié)果都是使用JMH取得的,并且都帶有通常的健康警告 。

    翻譯自: https://www.javacodegeeks.com/2015/02/optimum-method-concatenate-strings-java.html

    java字符連接字符串?dāng)?shù)組

    總結(jié)

    以上是生活随笔為你收集整理的java字符连接字符串数组_Java中连接字符串的最佳方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。