什么是更有效的 StringBuffer new() 或 delete(0, sb.length())?

2022-09-04 02:03:24

人们经常认为,避免创建对象(特别是在循环中)被认为是很好的做法。

那么,什么是最有效的?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?

}

我的意思是,有人可能会争辩说,创建一个对象比循环通过数组更快。


答案 1

首先是线程安全,与 相比,它的性能会很差。StringBuilder不是线程安全的,但因此速度更快。最后,我更喜欢使用 setLength 将长度设置为 0。StringBufferStringBuilder

sb.setLength(0)

这与你相似,除了你并不真正关心长度。也可能更快一些,因为它不需要“删除”任何东西。创建新的(或 StringBuffer)效率会降低。任何时候你看到Java正在创建一个新对象并将其放在堆上。.delete(...)StringBuildernew

注意:在查看了 和 的实现之后,将 length = 0 设置为,并将所有内容都设置为“这样您就可以获得一点胜利”.delete.setLength.delete.setLength'\0'.delete


答案 2

只是为了放大前面的评论:

从源来看,()总是调用(),但如果参数是(0,count),它将调用长度为零的(),这大概不会有任何影响。恕我直言,这应该优化,因为我打赌这是最常见的情况,但没关系。deleteSystem.arraycopyarraycopy

另一方面,使用(),如果需要,调用将通过调用()来增加StringBuilder的容量(恕我直言,另一种非常常见的情况应该优化),然后像()那样截断长度。setLengthensureCapacityInternaldelete

最终,这两种方法最终都设置为零。count

在这种情况下,两个调用都不会进行任何迭代。两者都进行不必要的函数调用。然而,确保CapacityInternal()是一个非常简单的私有方法,它邀请编译器优化它几乎不存在,所以()可能稍微更有效。setLength

我非常怀疑创建StringBuilder的新实例是否能像简单地设置为零一样有效,但我认为编译器可能会识别所涉及的模式并将重复的实例化转换为对(0)的重复调用。但在最好的情况下,这将是一次洗涤。而且您依赖于编译器来识别这种情况。countsetLength

执行摘要:setLength(0) 是最有效的。为了获得最高效率,请在创建 StringBuilder 时在其中预先分配缓冲区空间。


推荐