点击上方“Java精选”,选择“设为星标”

别问别人为什么,多问自己凭什么!

下方有惊喜,留言必回,有问必答!

每天 08:15 更新文章,每天进步一点点...

字符串拼接一般使用“+”,但是“+”不能满足大批量数据的处理,Java中有以下五种方法处理字符串拼接,各有优缺点,程序开发应选择合适的方法实现。

  1. 加号 “+”

  2. String contact() 方法

  3. StringUtils.join() 方法

  4. StringBuffer append() 方法

  5. StringBuilder append() 方法

经过简单的程序测试,从执行100次到90万次的时间开销如下表:

由此可以看出:

  1. 方法1 加号 “+” 拼接 和 方法2 String contact() 方法 适用于小数据量的操作,代码简洁方便,加号“+” 更符合我们的编码和阅读习惯;

  2. 方法3 StringUtils.join() 方法 适用于将ArrayList转换成字符串,就算90万条数据也只需68ms,可以省掉循环读取ArrayList的代码;

  3. 方法4 StringBuffer append() 方法 和 方法5 StringBuilder append() 方法 其实他们的本质是一样的,都是继承自AbstractStringBuilder,效率最高,大批量的数据处理最好选择这两种方法。

  4. 方法1 加号 “+” 拼接 和 方法2 String contact() 方法 的时间和空间成本都很高(分析在本文末尾),不能用来做批量数据的处理。

推荐下自己几个月熬夜整理的面试资料大全:

https://gitee.com/yoodb/eboo‍ks

源代码,供参考

package cnblogs.twzheng.lab2;/*** @author Tan Wenzheng**/
import java.util.ArrayList;
import java.util.List;import org.apache.commons.lang3.StringUtils;public class TestString {private static final int max = 100;public void testPlus() {System.out.println(">>> testPlus() <<<");String str = "";long start = System.currentTimeMillis();for (int i = 0; i < max; i++) {str = str + "a";}long end = System.currentTimeMillis();long cost = end - start;System.out.println("   {str + \"a\"} cost=" + cost + " ms");}public void testConcat() {System.out.println(">>> testConcat() <<<");String str = "";long start = System.currentTimeMillis();for (int i = 0; i < max; i++) {str = str.concat("a");}long end = System.currentTimeMillis();long cost = end - start;System.out.println("   {str.concat(\"a\")} cost=" + cost + " ms");}public void testJoin() {System.out.println(">>> testJoin() <<<");long start = System.currentTimeMillis();List<String> list = new ArrayList<String>();for (int i = 0; i < max; i++) {list.add("a");}long end1 = System.currentTimeMillis();long cost1 = end1 - start;StringUtils.join(list, "");long end = System.currentTimeMillis();long cost = end - end1;System.out.println("   {list.add(\"a\")} cost1=" + cost1 + " ms");System.out.println("   {StringUtils.join(list, \"\")} cost=" + cost+ " ms");}public void testStringBuffer() {System.out.println(">>> testStringBuffer() <<<");long start = System.currentTimeMillis();StringBuffer strBuffer = new StringBuffer();for (int i = 0; i < max; i++) {strBuffer.append("a");}strBuffer.toString();long end = System.currentTimeMillis();long cost = end - start;System.out.println("   {strBuffer.append(\"a\")} cost=" + cost + " ms");}public void testStringBuilder() {System.out.println(">>> testStringBuilder() <<<");long start = System.currentTimeMillis();StringBuilder strBuilder = new StringBuilder();for (int i = 0; i < max; i++) {strBuilder.append("a");}strBuilder.toString();long end = System.currentTimeMillis();long cost = end - start;System.out.println("   {strBuilder.append(\"a\")} cost=" + cost + " ms");}
}

测试结果:

  1. 执行100次, private static final int max = 100;

>>> testPlus() <<<{str + "a"} cost=0 ms
>>> testConcat() <<<{str.concat("a")} cost=0 ms
>>> testJoin() <<<{list.add("a")} cost1=0 ms{StringUtils.join(list, "")} cost=20 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=0 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=0 ms
  1. 执行1000次, private static final int max = 1000;

>>> testPlus() <<<{str + "a"} cost=10 ms
>>> testConcat() <<<{str.concat("a")} cost=0 ms
>>> testJoin() <<<{list.add("a")} cost1=0 ms{StringUtils.join(list, "")} cost=20 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=0 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=0 ms
  1. 执行1万次, private static final int max = 10000;

>>> testPlus() <<<{str + "a"} cost=150 ms
>>> testConcat() <<<{str.concat("a")} cost=70 ms
>>> testJoin() <<<{list.add("a")} cost1=0 ms{StringUtils.join(list, "")} cost=30 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=0 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=0 ms
  1. 执行10万次, private static final int max = 100000;

>>> testPlus() <<<{str + "a"} cost=4198 ms
>>> testConcat() <<<{str.concat("a")} cost=1862 ms
>>> testJoin() <<<{list.add("a")} cost1=21 ms{StringUtils.join(list, "")} cost=49 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=10 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=10 ms
  1. 执行20万次, private static final int max = 200000;

>>> testPlus() <<<{str + "a"} cost=17196 ms
>>> testConcat() <<<{str.concat("a")} cost=7653 ms
>>> testJoin() <<<{list.add("a")} cost1=20 ms{StringUtils.join(list, "")} cost=51 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=20 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=16 ms
  1. 执行50万次, private static final int max = 500000;

>>> testPlus() <<<{str + "a"} cost=124693 ms
>>> testConcat() <<<{str.concat("a")} cost=49439 ms
>>> testJoin() <<<{list.add("a")} cost1=21 ms{StringUtils.join(list, "")} cost=50 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=20 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=10 ms
  1. 执行90万次, private static final int max = 900000;

>>> testPlus() <<<{str + "a"} cost=456739 ms
>>> testConcat() <<<{str.concat("a")} cost=186252 ms
>>> testJoin() <<<{list.add("a")} cost1=20 ms{StringUtils.join(list, "")} cost=68 ms
>>> testStringBuffer() <<<{strBuffer.append("a")} cost=30 ms
>>> testStringBuilder() <<<{strBuilder.append("a")} cost=24 ms

查看源代码,以及简单分析

String contact 和 StringBufferStringBuilder 的源代码都可以在Java库里找到,有空可以研究研究。

推荐下自己做的 Spring boot 的实战项目:

https://gitee.com/yoodb/jing-xuan

1.其实每次调用contact()方法就是一次数组的拷贝,虽然在内存中是处理都是原子性操作,速度非常快,但是,最后的return语句会创建一个新String对象,限制了concat方法的速度。

public String concat(String str) {int otherLen = str.length();if (otherLen == 0) {return this;}int len = value.length;char buf[] = Arrays.copyOf(value, len + otherLen);str.getChars(buf, len);return new String(buf, true);}

2.StringBuffer 和 StringBuilder 的append方法都继承自AbstractStringBuilder,整个逻辑都只做字符数组的加长,拷贝,到最后也不会创建新的String对象,所以速度很快,完成拼接处理后在程序中用strBuffer.toString()来得到最终的字符串。

/*** Appends the specified string to this character sequence.* <p>* The characters of the {@code String} argument are appended, in* order, increasing the length of this sequence by the length of the* argument. If {@code str} is {@code null}, then the four* characters {@code "null"} are appended.* <p>* Let <i>n</i> be the length of this character sequence just prior to* execution of the {@code append} method. Then the character at* index <i>k</i> in the new character sequence is equal to the character* at index <i>k</i> in the old character sequence, if <i>k</i> is less* than <i>n</i>; otherwise, it is equal to the character at index* <i>k-n</i> in the argument {@code str}.** @param   str   a string.* @return  a reference to this object.*/public AbstractStringBuilder append(String str) {if (str == null) str = "null";int len = str.length();ensureCapacityInternal(count + len);str.getChars(0, len, value, count);count += len;return this;}
/*** This method has the same contract as ensureCapacity, but is* never synchronized.*/private void ensureCapacityInternal(int minimumCapacity) {// overflow-conscious codeif (minimumCapacity - value.length > 0)expandCapacity(minimumCapacity);}/*** This implements the expansion semantics of ensureCapacity with no* size check or synchronization.*/void expandCapacity(int minimumCapacity) {int newCapacity = value.length * 2 + 2;if (newCapacity - minimumCapacity < 0)newCapacity = minimumCapacity;if (newCapacity < 0) {if (minimumCapacity < 0) // overflowthrow new OutOfMemoryError();newCapacity = Integer.MAX_VALUE;}value = Arrays.copyOf(value, newCapacity);}

3.字符串的加号“+” 方法, 虽然编译器对其做了优化,使用StringBuilder的append方法进行追加,但是每循环一次都会创建一个StringBuilder对象,且都会调用toString方法转换成字符串,所以开销很大。

注:执行一次字符串“+”,相当于 str = new StringBuilder(str).append("a").toString();

4.本文开头的地方统计了时间开销,根据上述分析再想想空间的开销。常说拿空间换时间,反过来是不是拿时间换到了空间呢,但是在这里,其实时间是消耗在了重复的不必要的工作上(生成新的对象,toString方法),所以对大批量数据做处理时,加号“+” 和 contact 方法绝对不能用,时间和空间成本都很高。

作者:老坛酸菜WH

https://www.cnblogs.com/twzheng/p/5923642.html

公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!

------ THE END ------

精品资料,超赞福利!

>Java精选面试题<
3000+ 道面试题在线刷,最新、最全 Java 面试题!

期往精选  点击标题可跳转

【216期】面试官问:Spring Boot 全局异常拦截器?

【217期】大文件上传:秒传、断点续传、分片上传

【218期】玩转 Java 注解:元注解、内置注解、自定义注解的原理和实现

【219期】为什么代码规范要求 SQL 语句不要过多的 join?

【220期】面试官:一致性 Hash 是什么?在负载均衡中的应用

【221期】扔掉工具类,Mybatis 一个简单配置搞定数据加密解密!

【222期】一个适用于 Spring Boot 项目的轻量级 HTTP 客户端框架

【223期】面试官问:什么是 YAML?和 Spring Boot 有什么关系?

技术交流群!

最近有很多人问,有没有读者&异性交流群,你懂的!想知道如何加入。加入方式很简单,有兴趣的同学,只需要点击下方卡片,回复“加群”,即可免费加入交流群!

文章有帮助的话,在看,转发吧!

【224期】Java 字符串拼接五种方法的性能比较分析,从执行100次到90万次?相关推荐

  1. Java遍历Map五种方法

    一.Map集合遍历日常开发最常使用,简单总结五种方法差异. ①.Iterator+entrySet写法[推荐JDK8以下],Map.Entry是Map接口的内部接口,获取迭代器,然后依次取出每个迭代器 ...

  2. java 字符串 移位_使用位运算、值交换等方式反转java字符串-共四种方法

    在本文中,我们将向您展示几种在Java中将String类型的字符串字母倒序的几种方法. StringBuilder(str).reverse() char[]循环与值交换 byte循环与值交换 apa ...

  3. delphi64位 char数组转换string中文乱码_使用位运算、值交换等方式反转java字符串-共四种方法...

    在本文中,我们将向您展示几种在Java中将String类型的字符串字母倒序的几种方法. StringBuilder(str).reverse() char[]循环与值交换 byte循环与值交换 apa ...

  4. {转}Java 字符串分割三种方法

    http://www.chenwg.com/java/java-%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%88%86%E5%89%B2%E4%B8%89%E7%A7%8D%E6%9 ...

  5. java 字符串拆分技巧_{转}Java 字符串分割三种方法

    http://www.chenwg.com/java/java-%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%88%86%E5%89%B2%E4%B8%89%E7%A7%8D%E6%9 ...

  6. Java 字符串分割三种方法

    最近在项目中遇到一个小问题,一个字符串分割成一个数组,类似String str="aaa,bbb,ccc"; 然后以","为分割符,将其分割成一个数组,用什么方 ...

  7. 用python画四叶草代码-python—字符串拼接三种方法

    1.使用加号(+)号进行拼接 字符串拼接直接进行相加就可以,比较容易理解,但是一定要记得,变量直接相加,不是变量就要用引号引起来,不然会出错,另外数字是要转换为字符串才能够进行相加的,这点一定要记住, ...

  8. python字符串拼接变量_python—字符串拼接三种方法

    1.使用加号(+)号进行拼接 字符串拼接直接进行相加就可以,比较容易理解,但是一定要记得,变量直接相加,不是变量就要用引号引起来,不然会出错,另外数字是要转换为字符串才能够进行相加的,这点一定要记住, ...

  9. Swift忽略大小写搜索子字符串的三种方法及性能对比

    功能需求 在Swift中,字符串比较和搜索是很常见的操作.有时我们需要以特殊条件在一个字符串中搜索子字符串:比如忽略大小写或忽略变音符号. 在本篇博文里,我们将探讨Swift里三种特殊搜索字符串的方法 ...

最新文章

  1. sqlserver安装和简单的使用
  2. 分布式服务化系统一致性的“最佳实干”--转
  3. 资深美术师:3A转手游研发需要注意的方法
  4. [css] 举例说明:not()的使用场景有哪些
  5. java-linux-eclipse配置
  6. HIT Software Construction Review Notes(0-1 Introduction to the Course)
  7. zabbix安装笔记
  8. SQL转换时间的时分
  9. 常见NoSQL数据库概述
  10. Java利用MessageDigest获取字符串或文件MD5详解
  11. 网站头像: favicon.ico
  12. 系统管理指南:基本管理 第11 章• x86: 基于GRUB 的引导(任务)
  13. CDRX4X5X6X7X8下载安装失败的原因教程分享(CorelDRAW)
  14. 如何用excel做正交分析_利用Excel进行正交设计及分析
  15. python的OOP机制
  16. rockchip eDP 配置
  17. Excel分列-字母与汉字(前后)
  18. 字体加粗造成文字抖动
  19. 在excel中如何筛选重复数据_Excel数据筛选操作总结之数据透视表
  20. 最好用的数据库监控工具和数据库知识

热门文章

  1. SEO查询工具你只知道5118吗?这个工具包值得收藏
  2. chrony 时间同步详解
  3. 本题要求编写函数,将输入字符串的前3个字符移到最后
  4. ​真正的高手,都懂“概率权”
  5. windows 不小心删除了FlexNet Licensing Service 64 恢复方法
  6. C语言实现二叉树的非递归遍历
  7. SpringBoot 日志脱敏,开源组件太强了!
  8. 三态门有一个信号控制端en_单片机基础电路
  9. 宣化上人: “肉字里边两个人, 里边罩着外边人; 众生还吃众生肉, 仔细思量人吃人。”
  10. Google earth重登地图神器巅峰?看国产软件实力吊打行业老大