透彻分析String、StringBuilder和StringB
StringBuilder与String的性能对比
在名企面试官面前,如果仅仅回答“String不可变、StringBuilder可变、String不可被继承”等等卖萌的答案,只能等着被pass!
StringBuilder.apend源码分析
先来看一段代码
![](https://img.haomeiwen.com/i2916604/f76ffe846b9a4d4d.png)
输出结果
![](https://img.haomeiwen.com/i2916604/abe4152757140afe.png)
可以看出当进行大量的字符串拼接操作时,StringBuilder的append()方法比String的“+”快50倍以上!
我们来看一下它的源码调用过程:
首先会调用:StringBuilder append方法
![](https://img.haomeiwen.com/i2916604/f354cc8268105f69.png)
然后调用父类的AbstractStringBuilder append
![](https://img.haomeiwen.com/i2916604/537c16da25100602.png)
在该方法中有一个value属性值,是一个char类型的数组。
![](https://img.haomeiwen.com/i2916604/9d7dcb289882ca05.png)
if (newCount > value.length)
expandCapacity(newCount);
当新的容量大于原来的容量时就进行扩容操作:
![]()
其中会调用Arrays.copyOf方法,把老的数组copy到新创建的数组(长度为原来的2n+2倍)中去
然后返回给原来的数组。然后把value引用指向新的数组。
![]()
扩容操作完成后返回AbstractStringBuilder append方法,执行
str.getChars(0, len, value, count)
方法,该方法的作用是把字符串拷贝到stringbuilder本身的char数组当中去,如果不需要扩容则直接执行这个方法。
综上可以得到调用StringBuilder调用append方法的流程为:
![](https://img.haomeiwen.com/i2916604/a67dd21496e5648b.png)
所以附加以下“面向对象”的回答,会更加出彩:
StringBuilder是抽象类AbstractStringBuilder的一个具体实现
StringBuilder与AbstractStringBuilder重载了不同的append()方法
所有的append()方法都会返回this,这样就实现了链式编程
其他细节:
执行流程
![](https://img.haomeiwen.com/i2916604/dae129d9f7bc2419.png)
当数组容量不够的时候,会调用AbstractStringBuilder的expandCapacity()方法,将数组的容量扩大至原来的2n+2;
其中,expandCapacity()又调用了Arrays的copyOf()方法,目的是把原来数组的元素拷贝至新的数组。
![](https://img.haomeiwen.com/i2916604/e46e45e33f05f760.png)
![](https://img.haomeiwen.com/i2916604/d0e6d1cbfca00f82.png)
![](https://img.haomeiwen.com/i2916604/2bbb84262dff9e5a.png)
String+"H"分析
![](https://img.haomeiwen.com/i2916604/01326f065104af01.png)
概括一下整个过程:
- 新开辟一个length+1的数组
- 把原来的数组复制过来
- 在数组尾部再复制一个H
- 把原来value引用指向新的数组,旧数组会被GC回收器回收
![](https://img.haomeiwen.com/i2916604/eb2df000bce3523a.png)
同StringBuilder的append(),假设执行了65535次“+”,即:n=65535;那么,一共进行了多少次新对象、新数组的开辟,以及旧对象、旧数组的释放?
每次“+”,要new StringBuilder(),一共n次
每次“+”,要new char[str.length()+1],一共n次
故而,进行了2n次的开辟和释放。
![](https://img.haomeiwen.com/i2916604/a527d0c6ed1e07a7.png)
String+ 和StringBuilder对比
![](https://img.haomeiwen.com/i2916604/335a4b3ba39f1303.png)
![](https://img.haomeiwen.com/i2916604/690679879bd0b73a.png)
![](https://img.haomeiwen.com/i2916604/5c34779801a047f5.png)
![](https://img.haomeiwen.com/i2916604/242ce058bfa4132d.png)
![](https://img.haomeiwen.com/i2916604/98664c5540b50a09.png)