StringBuffer new() 和 delete(0, sb.length()) 哪个更有效?
人们经常认为避免创建对象(尤其是在循环中)被认为是良好的做法。
那么,对于StringBuffer
来说,什么是最有效的呢?
StringBuffer sb = new StringBuffer();
ObjectInputStream ois = ...;
for (int i=0;i<1000;i++) {
for (j=0;i<10;j++) {
sb.append(ois.readUTF());
}
...
// Which option is the most efficient?
sb = new StringBuffer(); // new StringBuffer instance?
sb.delete(0,sb.length()); // or deleting content?
}
我的意思是,有人可能会说创建对象比循环数组更快。
It is often argued that avoiding creating objects (especially in loops) is considered good practice.
Then, what is most efficient regarding StringBuffer
?
StringBuffer sb = new StringBuffer();
ObjectInputStream ois = ...;
for (int i=0;i<1000;i++) {
for (j=0;i<10;j++) {
sb.append(ois.readUTF());
}
...
// Which option is the most efficient?
sb = new StringBuffer(); // new StringBuffer instance?
sb.delete(0,sb.length()); // or deleting content?
}
I mean, one could argue that creating an object is faster then looping through an array.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
首先,
StringBuffer
是线程安全的,与StringBuilder
相比,其性能较差。 StringBuilder 不是线程安全的,但因此速度更快。最后,我更喜欢使用 设置长度。这与
.delete(...)
类似,只是您并不真正关心长度。也可能会快一点,因为它不需要“删除”任何东西。创建新的 StringBuilder (或 StringBuffer)效率会较低。每当您看到new
时,Java 都会创建一个新对象并将其放置在堆上。注意:查看
.delete
和.setLength
的实现后,.delete
设置length = 0,并且.setLength
将所有内容设置为'\0'
因此,您可能会通过.delete
获得一些胜利First
StringBuffer
is thread-safe which will have bad performance compared toStringBuilder
. StringBuilder is not thread safe but as a result is faster. Finally, I prefer just setting the length to 0 using setLength.This is similar to
.delete(...)
except you don't really care about the length. Also probably a little faster since it doesn't need to 'delete' anything. Creating a newStringBuilder
(or StringBuffer) would be less efficient. Any time you seenew
Java is creating a new object and placing that on the heap.Note: After looking at the implementation of
.delete
and.setLength
,.delete
sets length = 0, and.setLength
sets every thing to'\0'
So you may get a little win with.delete
只是为了放大之前的评论:
从源代码来看,
delete
() 总是调用System.arraycopy
(),但如果参数是 (0,count),它将调用长度为零的 arraycopy(),这可能不会产生任何效果。恕我直言,这应该被优化,因为我打赌这是最常见的情况,但没关系。另一方面,使用
setLength
() 时,如有必要,调用将通过调用ensureCapacityInternal
() 来增加 StringBuilder 的容量(另一个应该优化的非常常见的情况)恕我直言),然后像delete
() 那样截断长度。最终,这两种方法都只是将
count
设置为零。在这种情况下,两个调用都不会进行任何迭代。两者都会进行不必要的函数调用。然而,ensureCapacityInternal() 是一个非常简单的私有方法,它要求编译器对其进行优化,几乎使其不存在,因此
setLength
() 可能稍微更高效。我非常怀疑创建 StringBuilder 的新实例是否与简单地将
count
设置为零一样高效,但我认为编译器可能能够识别所涉及的模式,并且将重复的实例化转换为对setLength
(0) 的重复调用。但最好的情况是,这只是一次清洗。并且您依赖编译器来识别这种情况。执行摘要:setLength(0) 是最有效的。为了获得最大效率,请在创建 StringBuilder 时预先分配 StringBuilder 中的缓冲区空间。
Just to amplify the previous comments:
From looking at source,
delete
() always callsSystem.arraycopy
(), but if the arguments are (0,count), it will callarraycopy
() with a length of zero, which will presumably have no effect. IMHO, this should be optimized out since I bet it's the most common case, but no matter.With
setLength
(), on the other hand, the call will increase the StringBuilder's capacity if necessary via a call toensureCapacityInternal
() (another very common case that should have been optimized out IMHO) and then truncates the length asdelete
() would have done.Ultimately, both methods just wind up setting
count
to zero.Neither call does any iterating in this case. Both make an unnecessary function call. However ensureCapacityInternal() is a very simple private method, which invites the compiler to optimize it nearly out of existence so it's likely that
setLength
() is slightly more efficient.I'm extremely skeptical that creating a new instance of StringBuilder could ever be as efficient as simply setting
count
to zero, but I suppose that the compiler might recognize the pattern involved and convert the repeated instantiations into repeated calls tosetLength
(0). But at the very best, it would be a wash. And you're depending on the compiler to recognize the case.Executive summary: setLength(0) is the most efficient. For maximum efficiency, pre-allocate the buffer space in StringBuilder when you create it.
delete 方法是这样实现的:
正如您所看到的,它不会迭代数组。
The delete method is implemented this way:
As you can see it doesn't iterate through the array.