您的位置:首页 > 移动开发

StringBuilder/StringBuffer的insert, append复杂度分析

2014-10-22 15:23 971 查看
先来看一个cc150的例子:要串联一组strings合成单个string,可以用一下代码来实现。

public String joinWords(String[] words) {
String sentence = "";
for (String w : words) {
sentence += w;
}
return sentence;
}

这里使用string来存储结果,在每个loop里串联一次。string是immutable的,一旦初始化则不可再改变,所以串联的两个string都要被复制到一个新的string中。如果每个string的长度为x,总共有n个string,那么完成所有string的串联需要(x + 2x + 3x + ... + nx) 次操作,也就是O(xn^2)。

如果使用StringBuilder来做:

public String joinWords(String[] words) {
StringBuilder sentence = new StringBuilder();
for (String w : words) {
sentence.append(w);
}
return sentence.toString();
}

StringBuilder的默认constructor创建一个容量为16的字符串生成器。当这个builder装满之后,会自动增加一倍的空间,类似ArrayList。所以当使用append时,不用每次都复制string,整个过程只需要O(n)的时间。

现在我们需要往前串联strings,则要使用insert来做:

public String joinWords(String[] words) {
StringBuilder sentence = new StringBuilder();
for (String w : words) {
sentence.insert(0, w);
}
return sentence.toString();
}和append不一样,当调用insert时,StringBuilder会尽量减少string中被移动的元素,所以每当insert一次,就只会增加相应的空间,而不会为下次操作预留空间。第一个loop需要x次操作来移动并复制string,第二次需要2x个,以此类推。最终复杂度为O(n^2),效果和使用string的
sentence = w + sentence;
操作复杂度是一样的。

题外话:StringBuilder和StringBuffer唯一的不同之处就是StringBuilder在多线程中不能同步,而StringBuffer是可以的。所以对于只在单线程中使用的string,要选择用StringBuilder来操作。此外,StringBuilder比StringBuffer效率更高些,所以比较推荐使用。官方说明如下:

This class provides an API compatible with 
StringBuffer
, but with no guarantee of synchronization. This class is designed for use as a drop-in
replacement for 
StringBuffer
 in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class
be used in preference to 
StringBuffer
 as it will be faster under most implementations.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息