StringBuffer new() 和 delete(0, sb.length()) 哪个更有效?

发布于 2024-12-01 08:19:34 字数 484 浏览 2 评论 0原文

人们经常认为避免创建对象(尤其是在循环中)被认为是良好的做法。

那么,对于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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沫雨熙 2024-12-08 08:19:34

首先,StringBuffer 是线程安全的,与StringBuilder 相比,其性能较差。 StringBuilder 不是线程安全的,但因此速度更快。最后,我更喜欢使用 设置长度

sb.setLength(0)

这与 .delete(...) 类似,只是您并不真正关心长度。也可能会快一点,因为它不需要“删除”任何东西。创建新的 StringBuilder (或 StringBuffer)效率会较低。每当您看到 new 时,Java 都会创建一个新对象并将其放置在堆上。

注意:查看.delete.setLength的实现后,.delete设置length = 0,并且.setLength 将所有内容设置为 '\0' 因此,您可能会通过 .delete 获得一些胜利

First StringBuffer is thread-safe which will have bad performance compared to StringBuilder. StringBuilder is not thread safe but as a result is faster. Finally, I prefer just setting the length to 0 using setLength.

sb.setLength(0)

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 new StringBuilder (or StringBuffer) would be less efficient. Any time you see new 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

暮年慕年 2024-12-08 08:19:34

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

从源代码来看,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 calls System.arraycopy(), but if the arguments are (0,count), it will call arraycopy() 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 to ensureCapacityInternal() (another very common case that should have been optimized out IMHO) and then truncates the length as delete() 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 to setLength(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.

好听的两个字的网名 2024-12-08 08:19:34

delete 方法是这样实现的:

public AbstractStringBuilder delete(int start, int end) {
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (end > count)
        end = count;
    if (start > end)
        throw new StringIndexOutOfBoundsException();
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len;
    }
    return this;
}

正如您所看到的,它不会迭代数组。

The delete method is implemented this way:

public AbstractStringBuilder delete(int start, int end) {
    if (start < 0)
        throw new StringIndexOutOfBoundsException(start);
    if (end > count)
        end = count;
    if (start > end)
        throw new StringIndexOutOfBoundsException();
    int len = end - start;
    if (len > 0) {
        System.arraycopy(value, start+len, value, start, count-end);
        count -= len;
    }
    return this;
}

As you can see it doesn't iterate through the array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文