18. 【推荐】循环体内,字符串的连接方式,使用StringBuilder的append方法进行扩展。
说明:下例中,反编译出的字节码文件显示每次循环都会new出一个StringBuilder对象,然后进行append操作,
最后通过toString方法返回String对象,造成内存资源浪费。
反例:
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}

1.String是Java中一个不可变的类,所以他一旦被实例化就无法被修改。

不可变类的实例一旦创建,其成员变量的值就不能被修改。这样设计有很多好处,比如可以缓存hashcode、使用更加便利以及更加安全等。

但是,既然字符串是不可变的,那么字符串拼接又是怎么回事呢?

其实,所有的所谓字符串拼接,都是重新生成了一个新的字符串

2.
运算符重载:在计算机程序设计中,运算符重载(英语:operator overloading)是多态的一种。
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。

语法糖:语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·兰丁发明的一个术语,
指计算机语言中添加的某种语法,这种语法对语言的功能没有影响,但是更方便程序员使用。
语法糖让程序更加简洁,有更高的可读性。

3.使用+拼接字符串的实现原理

使用+拼接字符串,其实只是Java提供的一个语法糖
Java中的+对字符串的拼接,其实现原理是使用StringBuilder.append

4.concat实现

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);
}

这段代码首先创建了一个字符数组,长度是已有字符串和待拼接字符串的长度之和,
再把两个字符串的值复制到新的字符数组中,并使用这个字符数组创建一个新的String对象并返回。

5.StringBuffer和StringBuilder的实现原理

StringBuilder类也封装了一个字符数组: char[] value;
与String不同的是,它并不是final的,所以他是可以修改的。
另外,与String不同,字符数组中不一定所有位置都已经被使用,
它有一个实例变量,表示数组中已经使用的字符个数
int count;

append源码继承了AbstractStringBuilder类中的append方法:
public AbstractStringBuilder append(String str) {
if (str == null)
return appendNull();
int len = str.length();
ensureCapacityInternal(count + len);//这里传入的参数是增加字符串以后所需要的数组的最小长度
str.getChars(0, len, value, count);
count += len;
return this;
}

append会直接拷贝字符到内部的字符数组中,如果字符数组长度不够,会进行扩展。
StringBuffer和StringBuilder类似,最大的区别就是StringBuffer是线程安全的

StringBuffer的append方法:
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
该方法使用synchronized进行声明,说明是一个线程安全的方法

6.StringUtils.join实现

StringUtils.join的源代码:

public static String join(final Object[] array, String separator, final int startIndex, final int endIndex) {
if (array == null) {
return null;
}
if (separator == null) {
separator = EMPTY;
}

// endIndex - startIndex > 0: Len = NofStrings *(len(firstString) + len(separator))
// (Assuming that all Strings are roughly equally long)
final int noOfItems = endIndex - startIndex;
if (noOfItems <= 0) {
return EMPTY;
}

final StringBuilder buf = new StringBuilder(noOfItems * 16);

for (int i = startIndex; i < endIndex; i++) {
if (i > startIndex) {
buf.append(separator);
}
if (array[i] != null) {
buf.append(array[i]);
}
}
return buf.toString();
}

也是通过StringBuilder来实现的。

7.比较

long t1 = System.currentTimeMillis();

String str1 = "hello";
String str2 = "world";
StringBuilder str3 = new StringBuilder();
StringBuffer str4 = new StringBuffer();
for (int i = 0; i < 50000; i++) {
//str1 = str1 + str2;//cost:5325
//str1.concat(str2);//cost:5
//str3.append(str2);//cost:2
str4.append(str2);//cost:3

}
long t2 = System.currentTimeMillis();
System.out.println("cost:" + (t2 - t1));

StringBuilder<StringBuffer<concat<+<StringUtils.join

8.结论

直接使用StringBuilder的方式是效率最高的。因为StringBuilder天生就是设计来定义可变字符串和字符串的变化操作的。
如果不是在循环体中进行字符串拼接的话,直接使用+就好了。

如果在并发场景中进行字符串拼接的话,要使用StringBuffer来代替StringBuilder。

阿里巴巴Java开发手册_不建议在循环体中使用+进行字符串拼接的更多相关文章

  1. 为什么阿里巴巴Java开发手册中不建议在循环体中使用+进行字符串拼接?

    之前在阅读<阿里巴巴Java开发手册>时,发现有一条是关于循环体中字符串拼接的建议,具体内容如下: 那么我们首先来用例子来看看在循环体中用 + 或者用 StringBuilder 进行字符 ...

  2. 阿里巴巴 Java 开发手册 1.4.0

    一.编程规约(一) 命名风格1. [强制]代码中的命名均不能以下划线或美元符号开始,也不能以下划线或美元符号结束.反例: _name / __name / $name / name_ / name$ ...

  3. 《阿里巴巴 Java 开发手册》读书笔记

    偶然看到阿里巴巴居然出书了???趁着满减活动(节约节约....)我赶紧买来准备看看,刚拿到的时候掂量了好多下,总觉得商家给我少发了一本书,结果打开才知道..原来这本书这么小.... 编码规范的重要性 ...

  4. 《阿里巴巴Java开发手册》代码格式部分应用——idea中checkstyle的使用教程

    <阿里巴巴Java开发手册>代码格式部分应用--idea中checkstyle的使用教程 1.<阿里巴巴Java开发手册> 这是阿里巴巴工程师送给各位软件工程师的宝典,就像开车 ...

  5. 阿里巴巴Java开发手册——速读记录

    本随笔基于阿里巴巴Java开发手册V1.2,陆陆续续记录一些现阶段能理解的,有启发的内容,并将持续更新 最佳实践——插件使用已经发布为随笔!http://www.cnblogs.com/jiangbe ...

  6. 阿里巴巴 JAVA 开发手册

    阿里巴巴 JAVA 开发手册 1.0.0 阿里巴巴集团技术部 2016.12.7 首次向 Java 业界公开 一. 编程规约(一) 命名规约1. [强制]所有编程相关命名均不能以下划线或美元符号开始, ...

  7. 304902阿里巴巴Java开发手册1.4.0

    转自官网 前言 <阿里巴巴Java开发手册>是阿里巴巴集团技术团队的集体智慧结晶和经验总结,经历了多次大规模一线实战的检验及不断完善,系统化地整理成册,回馈给广大开发者.现代软件行业的高速 ...

  8. 【阿里巴巴Java开发手册1.7.0(嵩山版)】编程规约&MySQL 数据库规约

    阿里巴巴Java开发手册1.7.0(嵩山版) 一.编程规约 (一)命名风格 所有命名不得以下划线和$开始和结束. 所有命名不得以拼音或拼音英文混合. 类名使用UpperCamelCase风格. 方法名 ...

  9. 阿里巴巴Java开发手册———个人追加的见解和补充(一)

    先上干货,<阿里巴巴Java开发手册>的下载地址 https://yq.aliyun.com/articles/69327?spm=5176.100239.blogcont69327.15 ...

随机推荐

  1. Hadoop十年

    于 2006 年 1 月 28 日诞生的它改变了企业对数据的存储.处理和分析的过程,加速了大数据的发展,形成了自己的极其火爆的技术生态圈,并受到非常广泛的应用.在此为大家梳理 Hadoop 这十年的变 ...

  2. 多校联合训练&hdu5791 Two

    hdu5791 dp[i][j]表示的是序列A前i个数字和序列B前j个数字的公共子序列的总个数,那么的dp公式就可以这么表示 理解一下此公式若最尾部的a[i]和b[j]相等的话,那么单独的a[i]和b ...

  3. Code:template

    ylbtech-Code: 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   作者:ylbtech出处:http://ylbtech.cn ...

  4. libvirt, libvirt-python, libvirtd 关系浅析

    libvirt 官方解释:  http://libvirt.org/ 见分隔线以下. 我的理解:libvirt 作为一个中间层,封装了对下层虚拟化 hypervisor 的操作方法.也就是说,无论你是 ...

  5. 三 volatile关键字

    一:内存模型: 大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入.由于程序运行过程中的临时数据是存放在主存(物理内存)当中的,这时就存在一个问 ...

  6. [转]VS 2013 未找到与约束contractname Microsoft.VisualStudio.Utilities.IContentTypeRegistryService...匹配的导出

    前几天,将Visual studio 2013 update 3 升级到了update 5.打开原来的解决方案,出现了 未找到与约束 contractname Microsoft.VisualStud ...

  7. 《Spring实战》系列之Bean的装配-Days01

    1 自动化装配bean Spring通过两个方面实现对bean的自动装配 1 ) 组件扫描(component scaning):Spring会自动发现Spring上下文中的bean 2 ) 自动装配 ...

  8. Ajax 执行流程 有用 一点

    l 1.1使用JavaScript获得浏览器内置的AJAX引擎(XMLHttpRequest对象) l 1.2 通过AJAX引擎确定请求路径和请求参数 l 1.3 通知AJAX引擎发送请求 l AJA ...

  9. (转载)Windows无法安装到GPT分区形式磁盘解决办法

    之前使用的是windows7 + ubuntu18.04双系统,硬盘分区采用的是GPT格式.重装windows系统时,提示“windows无法安装到这个磁盘.选中的磁盘采用GPT分区形式”,导致安装失 ...

  10. try catch 块中debug时发现错误细节的一次记录

    在解决已有代码的一个问题时,有一个try catch块,基本代码如下: try { //do something } catch { LogHelper.Debug(typeof(myHelper), ...