Java:清除StringBuffer内容

发布于 2024-09-30 03:12:44 字数 586 浏览 8 评论 0原文

所有,

我想知道使用 setLength(0) 清除 StringBuffer 内容是否有意义。即这样做更好:

while (<some condition>)
{
    stringBufferVariable = new StringBuffer(128);
    stringBufferVariable.append(<something>)
                        .append(<more>)
                        ... ;
    Append stringBufferVariable.toString() to a file;
    stringBufferVariable.setLength(0);
}

我的问题:
1>这仍然比使用 String 对象附加内容具有更好的性能吗?

我不太确定重新初始化 StringBuffer 变量会如何影响性能,从而影响问题。

请发表您的评论

[编辑]:删除了关于与 StringBuilder 进行比较的第二个问题,因为我知道根据回复没有更多需要研究的了。

All,

I was wondering if clearing a StringBuffer contents using the setLength(0) would make sense. i.e. Is it better to do :

while (<some condition>)
{
    stringBufferVariable = new StringBuffer(128);
    stringBufferVariable.append(<something>)
                        .append(<more>)
                        ... ;
    Append stringBufferVariable.toString() to a file;
    stringBufferVariable.setLength(0);
}

My questions:
1 > Will this still have better performance than having a String object to append the contents?

I am not really sure how reinitializing the StringBuffer variable would affect the performance and hence the question.

Please pour in your comments

[edit]: Removed the 2nd question about comparing to StringBuilder since I have understood there nothing more to look into based on responses.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(6

守望孤独 2024-10-07 03:12:44

比连接字符串更好?

如果您问是否

stringBufferVariable.append("something")
                    .append("more");
...

会比使用 + 连接表现更好,那么通常是的。这就是这些类存在的全部原因。与更新 char 数组中的值相比,对象创建的成本较高。

现在,大多数(如果不是全部)编译器都会在简单情况下将字符串连接转换为使用 StringBuilder,例如 str = "something" + "more" + "...";。我可以看到的唯一性能差异是编译器不会具有设置初始大小的优势。基准会告诉您差异是否足够重要。使用 + 将使代码更具可读性。

根据我的阅读,编译器显然无法优化循环中完成的串联,因此

String str = "";
for (int i = 0; i < 10000; i++) {
    str = str + i + ",";
}

在这些情况下您仍然希望显式使用 StringBuilder。

StringBuilder 与 StringBuffer

StringBuilder 不是线程安全的,而 StringBuffer 是线程安全的,但它们在其他方面是相同的。在 StringBuffer 中执行的同步使其变慢,因此 StringBuilder 速度更快,除非需要同步,否则应使用它。

你应该使用setLength吗?

按照您当前示例的编写方式,我认为对 setLength 的调用不会给您带来任何好处,因为您在每次循环时都会创建一个新的 StringBuffer 。您真正应该做的是

StringBuilder sb = new StringBuilder(128);
while (<some condition>) {
    sb.append(<something>)
      .append(<more>)
      ... ;
    // Append stringBufferVariable.toString() to a file;
    sb.setLength(0);
}

这可以避免不必要的对象创建,并且在这种情况下 setLength 将仅更新内部 int 变量。

Better than concatenating strings?

If you're asking whether

stringBufferVariable.append("something")
                    .append("more");
...

will perform better than concatenating with +, then yes, usually. That's the whole reason these classes exist. Object creation is expensive compared to updating the values in a char array.

It appears most if not all compilers now convert string concatenation into using StringBuilder in simple cases such as str = "something" + "more" + "...";. The only performance difference I can then see is that the compiler won't have the advantage of setting the initial size. Benchmarks would tell you whether the difference is enough to matter. Using + would make for more readable code though.

From what I've read, the compiler apparently can't optimize concatenation done in a loop when it's something like

String str = "";
for (int i = 0; i < 10000; i++) {
    str = str + i + ",";
}

so in those cases you would still want to explicitly use StringBuilder.

StringBuilder vs StringBuffer

StringBuilder is not thread-safe while StringBuffer is, but they are otherwise the same. The synchronization performed in StringBuffer makes it slower, so StringBuilder is faster and should be used unless you need the synchronization.

Should you use setLength?

The way your example is currently written I don't think the call to setLength gets you anything, since you're creating a new StringBuffer on each pass through the loop. What you should really do is

StringBuilder sb = new StringBuilder(128);
while (<some condition>) {
    sb.append(<something>)
      .append(<more>)
      ... ;
    // Append stringBufferVariable.toString() to a file;
    sb.setLength(0);
}

This avoids unnecessary object creation and setLength will only be updating an internal int variable in this case.

流星番茄 2024-10-07 03:12:44

我只是关注问题的这一部分。 (其他部分之前已被问过并回答过很多次。)

我想知道使用 setLength(0) 清除 StringBuffer 内容是否有意义。

这取决于您使用的 Java 类库。在某些较旧的 Sun 版本的 Java 中,实现 StringBuffer.toString() 的前提是假设对 sb.toString() 的调用是对缓冲区执行的最后一件事。 StringBuffer 的原始后备数组成为 toString() 返回的 String 的一部分。随后尝试使用 StringBuffer 导致通过复制 String 内容创建并初始化一个新的后备数组。因此,在代码中尝试重用 StringBuffer 实际上会使应用程序变慢。

对于 Java 1.5 及更高版本,更好的编码方法如下:

    bufferedWriter.append(stringBufferVariable);
    stringBufferVariable.setLength(0);

这应该将字符直接从 StringBuilder 复制到文件缓冲区中,而不需要创建临时 String。如果 StringBuffer 声明位于循环之外,则 setLength(0) 允许您重用该缓冲区。

最后,只有当您有证据表明这部分代码是(或可能是)瓶颈时,您才应该担心所有这些。 “过早的优化是万恶之源”等等,等等。

I'm just focusing on this part of the question. (The other parts have been asked and answered many times before on SO.)

I was wondering if clearing a StringBuffer contents using the setLength(0) would make sense.

It depends on the Java class libraries you are using. In some older Sun releases of Java, the StringBuffer.toString() was implemented on the assumption that a call to sb.toString() is the last thing that is done with the buffer. The StringBuffer's original backing array becomes part of the String returned by toString(). A subsequent attempt to use the StringBuffer resulted a new backing array being created and initialized by copying the String contents. Thus, reusing a StringBuffer as your code tries to do would actually make the application slower.

With Java 1.5 and later, a better way to code this is as follows:

    bufferedWriter.append(stringBufferVariable);
    stringBufferVariable.setLength(0);

This should copy the characters directly from the StringBuilder into the file buffer without any need to create a temporary String. Providing that the StringBuffer declaration is outside the loop, the setLength(0) then allows you to reuse the buffer.

Finally, you should only be worrying about all of this if you have evidence that this part of the code is (or is likely to be) a bottleneck. "Premature optimization is the root of all evil" blah, blah.

对你再特殊 2024-10-07 03:12:44

对于问题2,StringBuilder会比StringBuffer表现得更好。 StringBuffer 是线程安全的,这意味着方法是同步的。字符串生成器不同步。因此,如果您拥有的代码将由一个线程运行,那么 StringBuilder 将具有更好的性能,因为它没有进行同步的开销。

正如 camickr 建议的那样,请查看 StringBuffer 和 StringBuilder 的 API 以获取更多信息。

您也可能对这篇文章感兴趣:微优化剧场的悲惨悲剧

For question 2, StringBuilder will perform better than StringBuffer. StringBuffer is thread safe, meaning methods are synchronized. String Builder is not synchronized. So if the code you have is going to be run by ONE thread, then StringBuilder is going to have better performance since it does not have the overhead of doing synchronization.

As camickr suggest, please check out the API for StringBuffer and StringBuilder for more information.

Also you may be interested in this article: The Sad Tragedy of Micro-Optimization Theater

野侃 2024-10-07 03:12:44

1>这仍然比使用 String 对象附加内容具有更好的性能吗?

是的,连接字符串很慢,因为您不断创建新的字符串对象。

2>如果使用 StringBuilder 会比 StringBuffer 表现更好,那么为什么呢?

您是否阅读过 StringBuilder 和/或 StringBuffer 的 API 描述?该问题已在此处解决。

我不太确定重新初始化 StringBuffer 变量会如何影响性能,从而影响问题。

我们创建一个测试程序。创建一个每次都会创建一个新的 StringBuffer/Builder 的测试。然后重新运行测试,将字符重置为 0,然后比较时间。

1 > Will this still have better performance than having a String object to append the contents?

Yes, concatenating Strings is slow since you keep creating new String Objects.

2 > If using StringBuilder would perform better than StringBuffer here, than why?

Have you read the API description for StringBuilder and/or StringBuffer? This issued is addressed there.

I am not really sure how reinitializing the StringBuffer variable would affect the performance and hence the question.

Well create a test program. Create a test that creates a new StringBuffer/Builder every time. Then rerun the test and just reset the characters to 0 and then compare the times.

左岸枫 2024-10-07 03:12:44

也许我误解了你问题中的某些内容...如果你只是在每次迭代开始时创建一个新的长度,为什么要将底部的长度设置为 0 呢?

假设该变量是该方法的局部变量,或者如果在方法外部声明该变量,则该变量不会被多个线程使用(如果它在方法外部,则您的代码可能存在问题),然后将其设为 StringBuilder。

如果您在循环外部声明 StringBuilder,则不需要每次进入循环时都创建一个新的 StringBuilder,但您需要在循环结束时将长度设置为 0。

如果您在循环内部声明 StringBuilder,则无需在循环结束时将长度设置为 0。

在循环外部声明它并将长度设置为 0 可能会更快,但我会测量两者,如果没有很大差异,则在循环内部声明变量。限制变量的范围是一个很好的做法。

Perhaps I am misunderstanding something in your question... why are you setting the length to 0 at the bottom if you are just creating a new one at the start of each iteration?

Assuming the variable is a local variable to the method or that it will not be using by multiple threads if it is declared outside of a method (if it is outside of a method your code probably has issues though) then make it a StringBuilder.

If you declare the StringBuilder outside of the loop then you don't need to make a new one each time you enter the loop but you would want to set the length to 0 at the end of the loop.

If you declare the StringBuilder inside of the loop then you don't need to set the length to 0 at the end of the loop.

It is likely that declaring it outside of the loop and setting the length to 0 will be faster, but I would measure both and if there isn't a large difference declare the variable inside the loop. It is good practice to limit the scope of variables.

风柔一江水 2024-10-07 03:12:44

是的! setLength(0) 是个好主意!这就是它的用途。更快的方法就是丢弃 stringBuffer &制作一个新的。它速度更快,不能说它内存效率高:)

yup! setLength(0) is a great idea! that's what its for. anything quicker would be to discard the stringBuffer & make a new one. its faster, can't say anything about it being memory efficient :)

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