java字符连接字符串数组

最近有人问我这个问题–在Java中使用+运算符连接字符串是否对性能不利?

这让我开始思考Java中连接字符串的不同方法,以及它们如何相互对抗。 这些是我要研究的方法:

  1. 使用+运算符
  2. 使用StringBuilder
  3. 使用StringBuffer
  4. 使用String.concat()
  5. 使用String.joinString.join新增功能)

我还尝试了String.format()但是它是如此缓慢,以至于我暂时不在本文中介绍。

在继续之前,我们应该分离两个用例:

  1. 将两个字符串串联在一起作为一个调用,例如在日志消息中。 由于这只是一个电话,您可能会认为性能几乎不是问题,但结果仍然很有趣,并且可以阐明该主题。
  2. 在一个循环中连接两个字符串。 在这里,性能更是一个问题,尤其是当循环很大时。

我最初的想法和问题如下:

  1. +运算符是用StringBuilder实现的,因此至少在连接两个String的情况下,它应产生与StringBuilder类似的结果。 幕后到底发生了什么?
  2. 在所有类的设计目的都是为了连接Strings并取代StringBuffer之后,StringBuilder应该是最有效的方法。 但是,与String.concat()相比,创建StringBuilder的开销是多少?
  3. StringBuffer是连接字符串的原始类–不幸的是,其方法是同步的。 确实不需要同步,随后它被不同步的StringBuilder代替。 问题是,JIT是否优化了同步?
  4. String.concat()应该适用于2个字符串,但是在循环中是否可以正常工作?
  5. String.join()比StringBuilder具有更多的功能,如果我们指示它使用空的定界符来连接String,它将如何影响性能?

我要解决的第一个问题是+运算符的工作方式。 我一直都知道它在幕后使用了StringBuilder,但是要证明这一点,我们需要检查字节码。

如今 ,查看字节码最简单的方法是使用JITWatch ,这是一个非常出色的工具,旨在了解JIT如何编译您的代码。 它有一个很棒的视图,您可以在其中与字节码(如果要转到该级别,还可以是机器码)并排查看源代码。

这是一个非常简单的方法plus2()的字节码,我们可以看到确实在第6行上创建了一个StringBuilder,并附加了变量a(第14行)和b(第18行)。

我认为将其与StringBuffer的手工使用进行比较会很有趣,因此我创建了另一个方法build2(),结果如下。

此处生成的字节码不如plus()方法那么紧凑。 StringBuilder存储在变量高速缓存中(第13行),而不是仅留在堆栈上。 我不知道为什么会这样,但是JIT也许可以做到这一点,我们将不得不看看时机如何。

无论如何,如果用plus运算符和StringBuilder将2个字符串连接在一起的结果显着不同,那将是非常令人惊讶的。

我写了一个小型的JMH测试来确定不同方法的执行方式。 首先让我们看一下两个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()。 毫不奇怪,因为它不必为每次调用创建StringBuilder / StringBuffer而付出性能损失。 虽然确实需要每次都创建一个新的String(这将在以后变得很重要),但是对于连接两个Sting的非常简单的情况,它更快。

另一点是,尽管产生了额外的字节码,但正如我们预期的那样,plus和StringBuilder是等效的。 StringBuffer仅比StringBuilder慢一点,这很有趣,这表明JIT必须做一些魔术来优化同步。

下一个测试将创建一个100个字符串的数组,每个字符串包含10个字符。 基准测试比较了将100个字符串连接在一起的不同方法所花费的时间。 参见下面的代码:

这次的结果看起来完全不同:

在这里,加号方法确实遭受了损失。 每当您遍历循环时,创建StringBuilder的开销就会减少。 您可以在字节码中清楚地看到这一点:

您可以看到每次执行循环时都会创建一个新的StringBuilder(第30行)。 JIT应该发现这一点并能够对其进行优化是有争议的,但是事实并非如此,使用+变得非常慢。

同样,StringBuilder和StringBuffer的性能完全相同,但是这次它们都比String.concat()快。 String.concat()在循环的每次迭代中创建新的String所付出的代价最终会增加,并且StringBuilder变得更加高效。

给定可以添加到此方法的所有其他功能,String.join()的效果非常好,但是,正如预期的那样,对于纯串联而言,它不是最佳选择。

摘要

如果要在单行代码中连接字符串,则我将使用+运算符,因为它最易读,并且对于单个调用而言,性能实际上并不重要。 还要提防String.concat(),因为您几乎肯定会需要执行空值检查 ,而其他方法则不需要这样做。

在循环中连接字符串时,应使用StringBuilder。 您可以使用StringBuffer,但我不一定在所有情况下都信任JIT来像基准测试中那样高效地优化同步。

我的所有结果都是使用JMH取得的,并且都带有通常的健康警告 。

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

java字符连接字符串数组

java字符连接字符串数组_Java中连接字符串的最佳方法相关推荐

  1. java 字符串驻留_Java中的字符串驻留

    最近在工作的时候,一句再正常不过的代码String a = "hello" + "world";被改成了new StringBuilder().append(& ...

  2. java 字符串 判断_Java中判断字符串是否相等的实现

    在最近的开发中,我踩到一个坑,过程是这样的.我需要在Java中判断两个字符串是否相等,按照以往的经历使用 == 双等号的操作符来判断,但是在Java中,这样写却没有实现我想要的效果.经过查阅资料后,把 ...

  3. java生成字符串数组_Java 生成随机字符串数组的实例详解

    Java 生成随机字符串数组的实例详解 利用Collections.sort()方法对泛型为String的List 进行排序.具体要求: 1.创建完List之后,往其中添加十条随机字符串 2.每条字符 ...

  4. java 字符串用法_Java中的字符串用法小结

    本文实例总结了Java中的字符串用法.分享给大家供大家参考.具体分析如下: 字符串的本质是char类型的数组,但在java中,所有用双引号""声明的字符串都是一个String类的对 ...

  5. java声明和初始化数组_Java 中初始化数组

    数组是一种有用的数据类型,用于管理在连续内存位置中建模最好的集合元素.下面是如何有效地使用它们. -- Chris Hermansen(作者) 有使用 C 或者 FORTRAN 语言编程经验的人会对数 ...

  6. java字符串转字符串列表_Java中的字符串列表示例

    java字符串转字符串列表 We have to read total number string i.e. "n", create a list of the Strings a ...

  7. C++接收字符串数组_Java 中初始化数组

    数组是一种有用的数据类型,用于管理在连续内存位置中建模最好的集合元素.下面是如何有效地使用它们. -- Chris Hermansen(作者) 有使用 C 或者 FORTRAN 语言编程经验的人会对数 ...

  8. java 字符和汉字比较_Java比较汉字字符串排序与C++比较汉字排序

    一.Java比较汉字 // Collator 类是用来执行区分语言环境的 String 比较的,这里选择使用CHINA Comparator cmp = Collator.getInstance(ja ...

  9. java 创建多维数组_java中如何创建一个多维数组?实例展示

    在互联网产业发展的越发如火如荼的今时今日,越来越多的人开始投入到新兴技术的学习当中去.java作为一门十分重要的编程语言,是许多人首选的学习对象.今天就来为大家介绍一下java中如何创建一个多维数组, ...

最新文章

  1. 在线协作沟通,以目标分解成任务树基础的团队配合
  2. 面对万亿级测序市场,纳米孔测序技术何去何从?
  3. 趋势科技4月移动client病毒报告
  4. selenium.common.exceptions.WebDriverException: Message: unknown error: cannot find Chrome binary
  5. python安装sqap_python文件I/O
  6. .NETCore中实现ObjectId反解
  7. mysql 数据表中查找重复记录
  8. Java中只存在值传递
  9. 打印出现:You've implemented -[UIApplicationDelegate application:didReceiveRemoteNotification:...
  10. 知识变现 常用课程制作实用工具大全(建议保存)
  11. java pdf417_java生成PDF417条码
  12. c语言check,C语言的CHECK-LIST
  13. Appdata文件夹
  14. Android虚拟机的理解和内存管理
  15. 京东云,走进产业数字化深处
  16. Python 英文电影中参演人员名单一般以某种方式进行排版显示
  17. Android在线购物商城 app端+后台
  18. 【技术邻】基于Ansys Icepak的散热器优化
  19. 机械加工工艺规程的制订
  20. CAD软件中坐标Z轴归零问题的两种解决办法

热门文章

  1. jzoj3910-Idiot的间谍网络【倍增,dfs】
  2. jzoj6275-[NOIP提高组模拟1]小L的数列【矩阵乘法,欧拉定理】
  3. 【LCT】【树状数组】Matches Are Not a Child‘s Play(luogu CF1137F)
  4. 【拓扑排序】【DP】旅行计划(luogu 1137)
  5. HDU5528 - Count a * b
  6. 18、java中的泛型
  7. (九)Spring 事务开发、事务属性详解
  8. laravel使用migrate操作数据库迁移
  9. 搭建ssh框架的步骤
  10. 2017蓝桥杯省赛---java---A---2(9数算式)