很多讲Java优化的文章都会强调对String拼接的优化。倒不用特意记,本质上在于对不可变类优势和劣势的理解上。

需要关注的是编译器对String拼接做出的优化,在简单场景下的性能能够与StringBuilder相当,复杂场景下仍然有较大的性能问题。网上关于这一问题讲的非常乱;如果我讲的有什么纰漏,也欢迎指正。

本文用到了反编译工具jad。在查阅网上关于String拼接操作的优化时发现了这个工具,能同时反编译出来源码和字节码,亲测好用,点我下载

String拼接的性能问题

优化之前,每次用”+”拼接,都会生成一个新的String。特别在循环拼接字符串的场景下,性能损失是极其严重的:

  1. 空间浪费:每次拼接的结果都需要创建新的不可变类
  2. 时间浪费:创建的新不可变类需要初始化;产生大量“短命”垃圾,影响 young gc甚至full gc

所谓简单场景

简单场景和复杂场景是我乱起的名字,帮助理解编译器的优化方案。

简单场景可理解为在一句中完成拼接:

int i = 0;String sentence = “Hello” + “world” + String.valueOf(i) + “”;System.out.println(sentence);

利用jad可看到优化结果:

int i = 0;String sentence = (new StringBuilder()).append(“Hello”).append(“world”).append(String.valueOf(i)).append(“”).toString();System.out.println(sentence);

是不是很神奇,竟然把String的拼接操作优化成了StringBuilder#append()!

此时,可以认为已经将简单场景的空间性能、时间性能优化到最优(仅针对String拼接操作而言),看起来编译器已经完成了必要的优化。你可以测试一下,简单场景下的性能能够与StringBuilder相当。但是——“但是”以前的都是废话——编译器的优化对于复杂场景的帮助却很有限了。

所谓复杂场景

所谓复杂场景,可理解为“编译器不确定(或很难确定,于是不做分析)要进行多少次字符串拼接后才需要转换回String”。可能表述不准确,理解个大概就好。

我们分析一个最简单的复杂场景:

String sentence = “”;for (int i = 0; i 

理想的优化方案

当然,无论什么场景,程序猿都可以手动优化:

  • 在性能敏感的场景使用StringBuilder完成拼接。
  • 在性能不敏感的场景使用更方便的String。

PS:别吐槽,这样的API设计是合理的,在合适的地方做合适的事

理想目标是把这件事交给javac和JIT:

  • 设定一个拼接次数的阈值,超过阈值就启动优化(对于javac有一个编译期的阈值,JIT有一个运行期的阈值,以分阶段优化)。
  • 优化时,在拼接前生成StringBuilder对象,将拼接操作换成StringBuilder#append(),继续使用该对象,直至“需要”String对象时,使用StringBuilder#toString()“懒加载”新的String对象。

该优化方案的难度在于代码分析:机器很难知道到底何时“需要”String对象,所以也很难在合适的位置注入代码完成“懒加载”。

虽然很难实现,但还是给出理想的优化结果,以供实际方案对比:

String sentence = “”;StringBuilder sentenceSB = new StringBuilder(sentence);for (int i = 0; i 

实际的优化方案

利用jad查看实际的优化结果:

String sentence = “”;for (int i = 0; i 

可以看到,实际上编译器的优化只能达到简单场景的最优:仅优化字符串拼接的一句。这种优化程度,对于上述复杂场景的性能提升很有限,循环时还是会生成大量短命垃圾,特别是字符串拼接到很大的时候,空间和时间上都是致命的。

通过对理想方案的分析,我们也能理解编译器优化的无奈之处:编译器无法(或很难)通过代码分析判断何时是最晚进行懒加载的时机。为什么呢?我们将代码换个形式可能更容易理解:

String sentence = “”;for (int i = 0; i 

观察第3行的代码,等式右侧引用了sentence。我肉眼知道这句话只完成了字符串拼接,机器呢?最起码,现在的机器还很难通过代码判断。

待以后将人工智能与编译优化结合起来,就算只能以90%的概率完成优化,也是非常cool的。

总结

这个问题我没有做性能测试。其实也没必要过于深究,与其让编译器以隐晦的方式完成优化,不如用代码进行主动、清晰的优化,让代码能够“自解释”。

那么,如果需要优化,使用StringBuilder吧。

string拼接_String拼接操作-的优化相关推荐

  1. 【STL】string详解(string类常用的操作函数、构造函数、赋值操作、子符串的拼接、查找和替换、比较、存取、插入和删除、获取)

    目录 1. string容器 简介 2. string类常用的操作函数 3. 构造函数 4. 赋值操作 5. 字符串拼接 6. 字符串查找和替换 7. 字符串比较 8. 字符串存取 9. 字符串插入和 ...

  2. 剖析java中的String之__拼接

    剖析java中的String之__拼接 分类: java 2011-08-24 17:46 31人阅读 评论(0) 收藏 举报 出处, http://blog.csdn.net/izard999/ar ...

  3. java中拼接和 的区别_浅析Java中String与StringBuffer拼接的区别

    学习笔记: 1.String拼接会创建一个新的String对象,存储拼接后的字符串: StringBuffer拼接是直接在本身拼接,会即时刷新. 2.String只能拼接String类型的字符串: S ...

  4. Java String类的相关操作

    Java String类的相关操作 一.如何遍历字符串 //法一 String str="hello world"; for(int i=0;i<str.length();i ...

  5. Java I/O 操作及优化建议

    Java I/O I/O,即 Input/Output(输入/输出) 的简称.就 I/O 而言,概念上有 5 种模型:blocking I/O,nonblocking I/O,I/O multiple ...

  6. Java拼接字符串 拼接双引号

    Java拼接字符串 拼接双引号 String sql = "<![CDATA[<?xml version="1.0" encoding="utf-8 ...

  7. C++字符串拼接 字符串拼接

    C++字符串拼接 字符串拼接 功能描述: 实现在字符串末尾拼接字符串 #include <iostream> #include <string> using namespace ...

  8. Stream Processing:滑动窗口的聚集(aggregation)操作的优化算法讲解

    本文将要讲解流处理中滑动窗口聚集操作的相关优化算法.将分别从下面几个方面讲解: 什么是滑动窗口? 什么是滑动窗口的聚集操作? 聚集操作的优化的必要性在哪里? 有哪些优化算法,它们的原理分别是什么? 4 ...

  9. 【控制】《复杂运动体系统的分布式协同控制与优化》-方浩老师-第6章-操作度优化条件下的移动机械臂协同搬运控制

    第5章 回到目录 第7章 第6章-操作度优化条件下的移动机械臂协同搬运控制 6.1 引言 6.2 问题描述 6.2.1 移动机械臂模型 6.2.2 协同搬运的优化问题描述 6.3 协同搬运过程中的移动 ...

最新文章

  1. 在.Net中进行跨线程的控件操作(上篇:Control.Invoke)
  2. 诺基亚基于区块链推环境感知服务,助力智慧城市发展
  3. SqlTransaction——事务详解 [转]
  4. 在线rss阅读聚合器lilina-0.7安装笔记
  5. python为什么没有指针_Python 没有指针,如何解算法题?
  6. 上传一个 游戏server架构图
  7. progressDialog 为什么设置了setProgress()方法无反应?
  8. 数字通信原理与TCP/IP
  9. Python数据分析U3-matplotlib可视化高级
  10. android 4.4 cts测试,android之CTS兼容性测试及FAIL issue
  11. Android 10 SystemUI 如何隐藏状态栏耳机图标和定位图标
  12. antdesign 柱状图_你绝对想不到柱形图背后有这么多故事
  13. 99乘法口诀表用python写_python 99乘法口诀表
  14. 将寄存器放入IOB的方法
  15. Android 10 正式版或将 9月3日 发布!
  16. 低轨卫星传播特性仿真与分析
  17. bat 输入密码_不记得密码了?教你查看设备保存的账号密码,绝对干货
  18. python Word 文档
  19. 软件系统维护是一项不吸引人的工作_“京极接口大师——链接一切软件系统和设备【智能制造吧】...
  20. 格式英语计算机,计算机英语论文大纲格式 计算机英语论文提纲如何写

热门文章

  1. php维护页面,php – Symfony2中的“维护网站”页面
  2. linux用java连接mysql_Java使用JDBC方式连接数据库
  3. 如何允许网页中的编辑器访问剪切板_Vditor下一代的 Markdown 编辑器,为未来而构建...
  4. python如何使用字典_Python-如何使用点“。” 访问字典成员?
  5. n个小球放入m个盒子中_飞么盒子卫生巾自助售卖机前景
  6. firefox火狐浏览器怎么清除缓存 火狐浏览器清理cookie教程
  7. Win7系统桌面壁纸换不了怎么办
  8. centos6.5配置Hadoop环境,运行wordcount例子
  9. js属性对象的hasOwnProperty方法
  10. socketmq 设置队列大小_[译] TCP的SYN队列和Accept队列