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

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

原文:https://blog.csdn.net/xiaoxixixiyang/article/details/40377187

猜你喜欢

转载自blog.csdn.net/weixin_42296449/article/details/85057176