Java中String与StringBuilder处理字符串效率存在差异的源码分析
申明一点:这篇博客只讨论stringbuilder中append(String str)方法;请看清楚,参数类型为String;
首先:字符串实际上就是一个char数组,也就是说String对象的值是保存在char[]中的;
存储具体值的char[]
在String中:
可以看到在String中存储字符串的是用final修饰的不可变char[];
在StringBuilder中:其构造方法是调用的父类AbstractStringBuilder的构造方法,存储字符串的也是一个char数组,具体的定义:
在StringBuilder中存储字符串的是一个可变char[];
StringBuilder中append(String str)的源码
StringBuilder 在使用append(String str)方法时调用了其父类的append(String str)方法;
这其中有2行关键代码:
第一个是方法:ensureCapacityInternal(count + len);
第二个是:String类的getchars()方法;
看到这里大家或许会有疑问,因为最后还不是调用的String类的getchars()来生成的新字符串吗??那既然这样为什么会说StringBuilder的效率比较高呢??why??
先不管那么多,上String类的getchars()源码再说:
System.arraycopy()是native方法,没法看源码了,到这儿也就到头了;
从arraycopy方法的注释来看:意思是将 value的值复制到char数组dst中,再对应到append调用getchars所传的参数来看,是将str的值复制到value(char数组)中;(对照append方法中调用getchars()时传递的参数方便理解)
看着这里大家心里都应该有点那啥数了。。
因为String中字符串数组value是final的(不可改变的),而StringBuilder是可变数组;所以StringBuilder比String快的原因,是因为,每次用String处理字符串时,都要创建一个数组,而StringBuilder则不用只需要在动态char数组后添加字符就行;这样StringBuilder就比String快。
看起来这样解释好像没有问题。。。。不过未完待续,先出去撸上一把,回来再续写,。。
======================继续分析=====================================
有点小激动,居然有人看了我的博客。继续努力写。。。。
上面的解释中有一个疑点:如何保证动态数组有足够大的空间给新添加的字符串???他对存储字符串的数组是不是做了些什么???
讲到这里我们先了解一下,StringBuilder的构造方法;
讲一下其中的2种构造方法,一个是无参构造,一个是带参构造(参数类型为String);
很明显,不管是在无参构造还是在带参构造:在初始化char数组中始终预留了16个长度的空间;
现在我们来理解一下2个很重要的成员变量:
count:注释写的很明显:就是字符串的长度比如:
StringBuilder sb = new StringBuilder(“abcde”);那么sb对象的count为:5,因为有五个字符,这个很好理解;
value.length 的值是什么呢?首先我们先来看:value是一个char数组;还是以上面的sb为例:
“abcde”这五个字符都是存储在数组value中的,value.length:表示value这个数组的长度,因为留有16个空位所以整个数组的长度为21,也就是说:value.length=21;
现在做一个综述:count:表示字符的个数;value.length:表示存储字符数组的长度(是数组的长度);
好了回到正题来,我们是如何保证存储StringBuilder对象的动态数组如何保证可以有足够的空间容纳下新加字符???
其实我们忽略了append()中调用的另一个方法:
(对比看上面的append方法)这两个参数:count:表示StringBuilder对象的字符个数,len:表示新添加的字符个数;这两个相加就表示:合并后总的字符数;举个列子:
StringBuilder sb = new StringBuilder(“abc”);
sb.append("de");这个例子中:count = 3;len = 2;合并后总字符数为 5;
接下来我们再看看这个方法里面是卖的什么狗皮膏药。。
很很简单的判断:就是判断合并后的总字符数是不是比原来存储StringBuilder对象的数组长度小,如果比原来的数组小,那很简单,原来的数组不用动,直接用就可以,不用创建新的数组;在这种情况下可以说,StringBuilder的效率比String高;
but!!!but !!!but 。。。如果合并后的总字符数超过了,存储StringBuilder对象数组的长度,那就要将StringBuilder得值复制到另外足够大的数组中了;在这种情况下的话。。。那和String那条咸鱼有什么区别?????!!!!!!!!!!根本就没有嘛
其实回到上一个问题:如何保证新加进来的字符有足够空间其实看到这里也就有了答案。。
所以说StringBuilder的效率不一定非得比String处理字符串的效率高;