string拼接_String拼接操作-的优化

1879f6934688f1d2c1ad0962c18da8c9.png

很多讲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吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/562846.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高斯消元法的c语言编程,列主元高斯消元法的C语言编程

列主元高斯消元法的C语言编程列主元高斯消元法基本思想:用高斯消元法求解线性方程组时,为避免小的主元,在进行第k步消元前,应该在第k列(k)元素aik(i k,(k)(k)例如|aikk| max|aik|,再把第ik个方程与第k,n)中找出第一个出…

cesium加载entity图片缩放_Cesium中级教程4 – 空间数据可视化(二)

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/Viewer中的Entity功能让我们看看Viewer为操作entities提供出来的功能函数。选中和描述点击Viewer中的entity将在entity的位置上呈现SelectionIndicator控件,提…

西安邮电大学卓越班c语言面试题,西安邮电大学C语言实验报告.docx

西 安 邮 电 学 院C语言程序设计课内实验报 告 书学院名称:计算机学院学生姓名:刘辉娟专业名称:计算机科学与技术班 级:计科1106学号:时间:2011-11-20至2011-11-30实验题目 数组一、????实验目的&#…

python 模糊匹配_很冷门,但非常实用的 Python 库

Python 是一个很棒的语言。它是世界上发展最快的编程语言之一。它一次又一次地证明了在开发人员职位中和跨行业的数据科学职位中的实用性。整个 Python 及其库的生态系统使它成为全世界用户(初学者和高级用户)的合适选择。它的成功和流行的原因之一是它强…

ccf魔数c语言,ccf 201609-4 交通规划

附上代码&#xff1a;#include#include#include#include#include#includeusing namespacestd;#define inf 0xfffffffintn, m;typedefstructNODE{intto;intcost;friendbool operator < (const NODE &a, const NODE &b) {return a.cost >b.cost;}}node;typedefstru…

python数据可视化是什么_Python数据分析:可视化

本文是《数据蛙三个月强化课》的第二篇总结教程&#xff0c;如果想要了解数据蛙社群&#xff0c;可以阅读对于我们数据分析师来说&#xff0c;不仅要自己明白数据背后的含义&#xff0c;而且还要给老板更直观的展示数据的意义。所以&#xff0c;对于这项不可缺少的技能&#xf…

c语言主函数名用户指定,C语言允许main函数带形参,且形参个数和形参名均可由用户指定。()...

听力原文&#xff1a;W: Oh, Ken, I have been meaning to talk to you.M: Hi, Denise! Whats up?W: I have this great job lined up to manage a clothing store at the mall.M: Oh, say in detail, please.W: Well, one of the professors in my department just told me a…

ENSP配置 实例一 不同VLAN间通信

ENSP配置 实例一 不同VLAN间通信 SW1 [SW1]vlan batch 10 20 [SW1]interface g0/0/1 [SW1-GigabitEthernet0/0/1]port link-type access [SW1-GigabitEthernet0/0/1]port default vlan 10 [SW1-GigabitEthernet0/0/1]int g0/0/2 [SW1-GigabitEthernet0/0/2]port link-type acce…

用python绘制心形_python小趣味_520绘制一个心形.

#!/usr/bin/env python#coding:utf-8 importturtleimporttime#画爱心的顶部 defLittleHeart():for i in range(200): turtle.right(1) turtle.forward(2)#输入表白的语句&#xff0c;默认I Love you love input(Please enter a sentence of love, otherwise the default is &q…

ENSP配置 实例二 单臂路由配置

ENSP配置 实例二 单臂路由配置 单臂路由配置 配置 路由&#xff1a; interface EigabitEthernet0/0/0 ip address 10.0.1.1 24 interface EigabitEthernet0/0/0.1 dot1q termination vid 10 ip address 192.168.1.254 24 arp broadcast enable interface EigabitEthernet0/0/…

用python画数学函数图像教程_Python 绘制你想要的数学函数图形

Python 非常热门&#xff0c;但除非工作需要没有刻意去了解更多&#xff0c;直到有个函数图要绘制&#xff0c;想起了它。结果发现&#xff0c;完全用不着明白什么是编程&#xff0c;就可以使用它完成很多数学函数图的绘制。 通过以下两个步骤&#xff0c;就可以进行数学函数的…

ENSP配置 实例三 静态路由配置

ENSP配置 实例三 静态路由配置 R1配置命令 system-view [R1]interface Ethernet 0/0/0 [R1-Ethernet0/0/0]ip add 192.168.1.254 24 [R1-Ethernet0/0/0]quit [R1]interface tEthernet 0/0/1 [R1-Ethernet0/0/1]ip addr 10.0.12.1 24 [R1-Ethernet0/0/1]quit [R1]ip route-stati…

单片机 c语言 概念题,(C语言版)单片机复习题.doc

单片机复习题一、名词解释1、时序&#xff1a;按照时间顺序显示的对象(或引脚、事件、信息)序列关系。2、指令&#xff1a;CPU用于指挥功能部件完成某一指定动作的指示和命令。3、变量&#xff1a;在程序执行过程中&#xff0c;数值可以发生改变的量称为变量。4、伪指令&#x…

python 散点图 不同颜色_python – pandas – 每个点都有不同颜色图例的散点图

以下方法将根据您的数据框创建颜色列表,然后使用每种颜色的标签绘制一个点&#xff1a; import matplotlib.pyplot as plt import matplotlib.cm as cm import matplotlib.colors as colors import numpy as np import pandas as pd fig, ax plt.subplots() df pd.DataFrame(…

ENSP配置 实例四 默认路由配置

ENSP默认路由配置 1&#xff0c;配置R1路由器 sys ##进入系统视图模式 [Huawei]sys R1 ##修改名字 [R1]int e0/0/0 ##进入接口 [R1-Ethernet0/0/0]ip add 192.168.1.254 24 ##配置ip地址 [R1-Ethernet0/0/0]undo shut ##开启物理接口 [R1-Ethernet0/0/1]int e0/0/1 [R1-Etherne…

套汇算法c语言,在金字塔下实现套利策略的测评

瀑布线是指用异同移动平均线(MACD)指标绘制的移动平均线&#xff0c;用于在证券中生成买入和卖出信号。瀑布线或信号线是交易者用来预测未来价格趋势的MACD指标线的九个周期指数移动平均线(EMA)。虽然九周期EMA是瀑布线的默认设置&#xff0c;但交易者可以调整EMA的长度以适应其…

python数据分析函数大全_python中数据分析常用函数整理

一. apply函数 作用&#xff1a;对 DataFrame 的某行/列应用函数之后&#xff0c;Apply 返回一些值。函数既可以使用默认的&#xff0c;也可以自定义。注意&#xff1a;在第二个输出中应用 head() 函数&#xff0c;因为它包含了很多行。 #创建一个新函数 def num_missing(x): r…

ENSP配置 实例五 RIP配置

ENSP配置 实例五 RIP配置 配置 R1 sy [Huawei]sy R1 [R1]int e0/0/0 [R1-Ethernet0/0/0]ip add 192.168.1.254 24 [R1-Ethernet0/0/0]int e0/0/1 [R1-Ethernet0/0/1]ip add 10.0.12.1 24 [R1-Ethernet0/0/1]q [R1]rip 1 [R1-rip-1]network 192.168.1.0 [R1-rip-1]network 10.0.…

如何用c语言读文件,如何用C语言读写文件

打开文件fopen("需要打开的路径")然后使用fgets函数读取行#include<stdio.h>#include<stdlib.h>#include<string.h>#defineMAX_LINE1024 intmain() { charbuf[MAX_LINE]; /*缓冲区*/ FILE*fp; /*文件指针*/ intlen; /*行字符个数*/if((…

ENSP配置 实例六 OSPF配置

ENSP配置 实例六 OSPF配置 R1 [R1]interface e0/0/0 [R1-Ethernet0/0/0]ip add 192.168.1.254 24 [R1-Ethernet0/0/0]int e0/0/1 [R1-Ethernet0/0/1]ip add 10.0.12.1 24 [R1]ospf 1 router-id 1.1.1.1 [R1-ospf-1]area 0 [R1-ospf-1-area-0.0.0.0]network 192.168.1.0 0.0.0.…