博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
StringBuilder源码分析
阅读量:3781 次
发布时间:2019-05-22

本文共 1996 字,大约阅读时间需要 6 分钟。

StringBuilder是平常编程中比较常用的JDK下的类之一。在字符串的拼接中发挥着重大的作用。可能很多人对于StringBuilder的认识并不深刻。这里通过我的理解来阐述一下StringBuilder。

1.为什么要使用StringBuilder?

这里很多人可能会说有“+”写出来的代码可能不是那么雅观,可能算做一个,另外更重要的原因是众所周知的性能。这在很多面试题里会屡试不爽的提在字符串拼接的情况下使用StringBuilder,在for循环下更是如此。why?这里归根结底是String的final特性决定的。如果细心的同学可以看一下String的源码中存储的数组就是final类型的。String本身是无法达到扩容的目的。

2.为什么StringBuilder可以得到性能上的提升。

StringBuilder内部也是一个char数组,这和String内部的存储实现无异。下面用具体的代码来看一下使用String和StringBuilder在性能上的差异和性能到底损失在什么地方。

@Test    public void test3(){        String s = null;        for(int i=0;i<1000;i++){            s +=i;        }    }        @Test    public void test4(){        StringBuilder builder = new StringBuilder();        for(int i=0;i<1000;i++){            builder.append(i);        }    }    @Test    public void test5(){        StringBuilder builder = new StringBuilder(3000);        for(int i=0;i<1000;i++){            builder.append(i);        }    }
test3方法

采用最笨的+操作符,上面已经说String是final类型的,可以看一下中间会产生出多少中间对象,可以简单的算一下,本身循环1000次会有1000个对象,另外实现+操作后又产生1000个对象。最后垃圾回收多少对象?回收1999个对象。只保留最后一个s对象。

test4方法

采用不初始化初始容器的方式进行,这也是大部分程序员能做到的。这里会产生多少对象呢?在外面看来是1001个对象,其实不是这样的。这里又要看一下StringBuilder的初始容量是16。当i=13的时候出现了一次扩容,看一下内部的会用到System.arrayCopy来实现一个扩容机制。这里再回到StringBuilder内部的存储是采用char数组实现存储的,而这个char[]的初始容量就是16,这样当i=13的时候会发现原来的数组已经装不下了,这时候怎么办?这时候首先申请一个更大容量的数组,新申请数组的大小是多少呢?是(当前容量的大小+1)*2,也就是34,很多人说我这时候加入的字符串还是大于扩充的容量怎么办,这里做一个处理,就是如果发现加进来的字符串的大小大于当前新申请的容量,就以新加进来的字符串的大小作为申请容易的大小。这里说的有点绕,看代码会清晰很多。

回到我所说的test4例子,根据上面的分析,其实StringBuilder需要做几次扩容才能完成,这里性能损失会在哪,一个是数组copy,另外一个就是扩容产生的垃圾对象需要JVM回收都会造成性能损耗。算一下这里要扩容几次。要扩容8次,中间就会产生8个中间对象需要JVM回收,而越往后面垃圾对象越大。

test5方法

test5在test4上面的改进主要就是初始化容量,这么做的好处就是省去了8次扩容产生的性能损耗和JVM回收垃圾的时间。

结论

所以在知道当前你append字符串容量的情况下可以指定其大小,在某些场景下有不少的性能提升。上面的分析同样可以平移到ArrayList,HashMap等内部采用数组实现的结构中。

3.如何计算需要初始化容量的大小?

String类型好算一些,length就可以了。像一些int类型,long类型它们需要申请多少空间呢?举一个简单的例子,像int类型的1000在StringBuilder需要占几个?答案是4个,如果去看一下源码就知道,它其实是转成String存,当然内部并没有强转成String,而是用了getChars方法。里面用了一些小技巧来获得一些性能的提升,有兴趣的同学也可以去看一下StringBuilder的实现。

4.具体的性能有多大的提升?

这里有兴趣的同学可以去压测一下。

转载地址:http://mkqvn.baihongyu.com/

你可能感兴趣的文章
员工管理系统五:增删改员工实现
查看>>
Redis的安装与卸载
查看>>
项目阶段五:验证码
查看>>
项目阶段五:购物车
查看>>
项目阶段六:订单模块的数据库准备与dao、service层
查看>>
项目阶段六:后台管理的订单模块
查看>>
练习——图书管理系统八(根据图书编号填充图书名称下拉控件和验证手机号)
查看>>
将windows下文件上传至服务器中
查看>>
正则表达式:贪婪模式与懒惰模式
查看>>
机器学习之sklearn.preprocessing.LabelBinarizer()的用法
查看>>
决策树剪枝的思想
查看>>
创建二叉树和遍历二叉树
查看>>
算法训练 区间k大数查询
查看>>
算法训练 K好数
查看>>
2021北京交通大学计算机专硕初试经验分享
查看>>
2021北京交通大学计算机专硕复试经验分享
查看>>
简单实现一个数组、链表
查看>>
关于从其他程序切回word文档时卡顿问题的解决办法
查看>>
Linux安装Java环境
查看>>
Java集合 ArrayList原理
查看>>