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

来源:互联网 发布:php 开发客户端 编辑:程序博客网 时间:2024/05/18 03:45

先来看一个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.


0 0