如何清空或清除一个StringBuilder?

13 浏览
0 Comments

如何清空或清除一个StringBuilder?

我在一个循环中使用StringBuilder,并且每隔x次迭代我想要清空它并重新开始一个空的StringBuilder,但是我在文档中找不到类似于.NET StringBuilder.Clear的方法,只有delete方法,看起来过于复杂。\n那么,在Java中清空一个StringBuilder的最佳方法是什么?

0
0 Comments

清空或清除一个StringBuilder的方法有两种。第一种是使用delete方法,通过删除从索引0到末尾的字符来实现清空。代码如下:

myStringBuilder.delete(0, myStringBuilder.length());

第二种方法是使用setLength方法,将长度设置为0,从而清空StringBuilder。代码如下:

myStringBuilder.setLength(0);

这两种方法都可以达到清空StringBuilder的效果。然而,使用delete方法可能不够高效,因为它需要执行删除操作。相比之下,使用setLength方法更加高效,因为它直接将长度设置为0,不需要执行删除操作。

如果在函数中将一个StringBuilder对象作为输出参数传递,那么创建新的StringBuilder对象是不可取的。因此,使用setLength方法是更加高效的选择。

某些情况下可以在参数中使用new关键字创建新的StringBuilder对象,例如`function(new StringBuilder())`。但是每次函数调用都会创建一个新的StringBuilder对象,这样做可能不够高效。

清空或清除一个StringBuilder的方法有两种,分别是使用delete方法和setLength方法。根据具体的情况选择合适的方法可以提高代码的效率。

0
0 Comments

如何清除或清空一个StringBuilder?

有两种选择,使用setLength(0)来重置StringBuilder或者在每次迭代中创建一个新的StringBuilder。根据使用情况,这两种方法都有优缺点。

如果事先知道StringBuilder的预期容量,每次创建一个新的StringBuilder应该与设置新的长度一样快。这也有助于垃圾收集器,因为每个StringBuilder的生命周期相对较短,垃圾收集器对此进行了优化。

当不知道容量时,重复使用同一个StringBuilder可能更快。每次添加时超过容量时,都必须分配一个新的支持数组并复制先前的内容。通过重复使用同一个StringBuilder,它将在一些迭代后达到所需的容量,之后就不会再有任何复制。

谢谢,我忘记了带有容量参数的构造函数。

如果使用setLength(0),这是否意味着它保持内部缓冲区的当前长度?我的担忧是我不想创建一个新的StringBuffer,因为我预计有时候会有相当长的字符串,因此我开始时有一个相当大的缓冲区大小(4k或32k)。所以,听起来使用setLength(0)可能更快。但是,如果StringBuffer分配的空间从不收缩,我可能会耗尽内存(这是在内存紧张的Android环境下)。

是的,内部缓冲区保持当前长度。你可以在android.googlesource.com/platform/libcore/+/master/luni/src/…上找到Android的实际实现。一旦你完成了添加字符的操作,你可以使用trimToSize方法释放不需要的空间。

你写道:“根据使用情况,这两种方法都有优缺点。”你能给我一些在每次迭代中创建新的StringBuilder更好的例子吗?

一个例子是如果你想要并行处理。

创建一个新的StringBuilder具有更好的可维护性优势。重复使用一个变量意味着它会分散在代码中。变量通常应该局限于最紧密的范围,这样可以使代码更简单易懂。这可能听起来很抽象,但当你编写将被大量人员长时间阅读和维护的代码时,它很重要。

0
0 Comments

如何清空或清除一个StringBuilder?

有两种方法可以实现:

1. 使用stringBuilderObj.setLength(0)。

2. 重新分配一个新的StringBuilder对象,使用new StringBuilder(),而不是清除缓冲区。请注意,对于性能关键的代码路径来说,这种方法可能比setLength方法更慢(因为需要分配一个具有新缓冲区的新对象,旧对象变为可回收的等等)。

如果不太担心性能,除非有很大的差异,只要以一种不会让未来的开发人员纳闷为什么以某种方式进行的方式来执行就可以了。

此外,我认为重新分配比使用两个索引的delete方法更清晰,但这可能是一个偏好问题。

不,这样并不便宜!你怎么能这么说?假设你有一个容量为1000个字符的缓冲区。然后你将其处理掉(为GC工作)并创建一个新的(为分配器工作)。将文本长度设置为零(对CPU几乎没有工作量)并重用同一个缓冲区会更快。

哦,回答晚了:我在想的是StringBuffer.delete(idx, len)。另一方面,执行setLength需要迭代整个缓冲区并将每个字符设置为null(例如kickjava.com/src/java/lang/AbstractStringBuilder.java.htm)。根据缓冲区的大小,这可能也是昂贵的。另一方面,除非它是极致的性能代码,否则选择最清晰的方式,并不要花时间进行微优化。

在你提供的链接中,setLength(0)不会像你说的那样进行迭代,只有在新长度大于已使用字符数量时才会这样做(0长度不可能发生)。从性能上看,setLength(0)似乎是最好的选择,而且似乎是清空缓冲区非常明确的含义。

这不总是可能的,比如将StringBuffer作为参数传递给一个方法。setLength(0)是正确的方法。

是的,我们必须迭代整个长度并将每个项目设置为null,以清除StringBuilder。这是Java源代码的链接。在你提供的链接中,只有count < newLength时才会这样做,但如果newLength为0,那是不可能发生的。

我有点明白了,现在你确认了我的想法。

你是绝对正确的-我有一对类,分别管理和表示统计数据,在输出时需要动态构建包含许多格式化值的长字符串。重用同一个StringBuilder而不是在每个统计输出上重新分配减少了250毫秒的打印时间!

在Android上确认。setLength(0)的速度是new StringBuilder(200)的两倍。使用无参数构造函数没有任何区别,可能是因为我只需要构建短字符串。

有人能解释一下为什么使用length(0)比重新分配更快吗?

只需setLegnth(0)。建议创建一个新的StringBuilder是不合适的。如果StringBuilder变得很大(比如100MB),那么丢弃它以便反复重新创建是没有意义的,因为清空缓冲区的意图是为了重用它。

这有点晚了,但是setLength不会造成内存泄漏。它重用同一个缓冲区,可能比你精确需要的要大或小,但这是预期的、正确的和性能最佳的行为。当StringBuilder被回收时,内存将被正确地回收,因此这绝对不能称为内存泄漏。如果在任何时候需要实际回收内存,只需调用stringBuilder.trimToSize()来回收所有不必要的内存,但这与此问题无关。

有些人似乎正在发布Java源代码的链接,以显示setLength(0)需要做多少工作,但当请求的长度为0时,所有这些工作都会被绕过。当调用长度为0的方法时,绝对不会发生请求的长度大于当前缓冲区的情况。显然,setLength(0)是最高效的,而且这在百万次迭代循环中是有区别的。在我的书中,避免实例化100万个不必要的StringBuilders并强制GC清理这个混乱是"不必要的预优化"。

和其他人一样,感谢您的反馈。我知道这是一个旧的回答,但我已经编辑了它,以包含更多关于性能影响的内容,至少让人们更多地考虑他们正在编写的代码的性能影响。

0