有人告诉我,使用StringBuffer
Java连接字符串比使用+
运算符String
s 更有效.当你这样做时会发生什么?有什么StringBuffer
不同的做法?
最好使用StringBuilder(它是一个不同步的版本;你什么时候并行构建字符串?)这几天,几乎在所有情况下,但这是发生的事情:
当你使用+两个字符串时,它会编译如下代码:
String third = first + second;
对于这样的事情:
StringBuilder builder = new StringBuilder( first ); builder.append( second ); third = builder.toString();
因此,仅举几个例子,通常没有什么区别.但是当你构建一个复杂的字符串时,你经常需要处理更多的事情.例如,您可能正在使用许多不同的附加语句,或者像这样的循环:
for( String str : strings ) { out += str; }
在这种情况下,一个新的StringBuilder
实例,以及一个新的String
(新值out
- String
s为不可变的)需要在每一次迭代.这非常浪费.用一个单位替换它StringBuilder
意味着你可以只生成一个String
而不用String
你不关心的s来填充堆.
对于简单的连接,例如:
String s = "a" + "b" + "c";
使用它是毫无意义的StringBuffer
- 正如jodonnell指出的那样,它将被巧妙地翻译成:
String s = new StringBuffer().append("a").append("b").append("c").toString();
但是在循环中连接字符串是非常不合格的,例如:
String s = ""; for (int i = 0; i < 10; i++) { s = s + Integer.toString(i); }
在此循环中使用string将在内存中生成10个中间字符串对象:"0","01","012"等等.使用StringBuffer
您编写相同内容时,只需更新一些内部缓冲区,StringBuffer
而不创建您不需要的中间字符串对象:
StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(i); }
实际上,对于上面的示例,您应该使用StringBuilder
(在Java 1.5中引入)而不是StringBuffer
- StringBuffer
因为它的所有方法都是同步的,所以稍微重一些.
一个人不应该比另一个人快.在Java 1.4.2之前不是这样,因为当使用"+"运算符连接两个以上的字符串时,String
将在构建最终字符串的过程中创建中间对象.
但是,随着Java文档的StringBuffer使用"+"操作符州,至少从Java 1.4.2编译为创建StringBuffer
和append()
荷兰国际集团的许多字符串给它.所以没有区别,显然.
但是,在循环中使用向另一个添加字符串时要小心!例如:
String myString = ""; for (String s : listOfStrings) { // Be careful! You're creating one intermediate String object // for every iteration on the list (this is costly!) myString += s; }
但请记住,通常用"+"连接几个字符串比使用append()
它们更清晰.
在引擎盖下,它实际上创建并附加到StringBuffer,在结果上调用toString().所以你使用它实际上并不重要.
所以
String s = "a" + "b" + "c";
变
String s = new StringBuffer().append("a").append("b").append("c").toString();
对于在单个语句中的一堆内联追加,这是正确的.如果你在多个语句的过程中构建你的字符串,那么你就是在浪费内存,而StringBuffer或StringBuilder是你更好的选择.
我认为给定jdk1.5(或更高版本)并且你的连接是线程安全的,你应该使用StringBuilder而不是StringBuffer http://java4ever.blogspot.com/2007/03/string-vs-stringbuffer-vs-stringbuilder.html 至于速度的提升:http: //www.about280.com/stringtest.html
我个人认为代码是为了可读性,所以除非你发现字符串连接使你的代码变得相当慢,否则请使用哪种方法使代码更具可读性.
在某些情况下,由于编译器执行优化,这已经过时,但一般问题是代码如下:
string myString=""; for(int i=0;i将按以下方式行事(每一步都是下一个循环迭代):
构造一个长度为1的字符串对象,值为"x"
创建一个大小为2的新字符串对象,将旧字符串"x"复制到其中,在位置2中添加"x".
创建一个大小为3的新字符串对象,将旧字符串"xx"复制到其中,在位置3中添加"x".
... 等等
如您所见,每次迭代都需要复制一个字符,导致我们在每个循环中执行1 + 2 + 3 + 4 + 5 + ... + N个操作.这是O(n ^ 2)操作.但是,如果我们事先知道我们只需要N个字符,我们可以在一次分配中完成,只使用我们使用的字符串中的N个字符的副本 - 仅仅是O(n)操作.
StringBuffer/StringBuilder避免这种情况,因为它们是可变的,因此不需要反复复制相同的数据(只要有空间可以复制到它们的内部缓冲区中).它们避免执行分配和复制,与按当前大小的比例过度分配缓冲区所做的附加次数成比例,给予摊销的O(1)追加.
然而值得注意的是,编译器通常会自动将代码优化为StringBuilder样式(或者更好 - 因为它可以执行常量折叠等).