如何清除或清空StringBuilder?

我在循环中使用StringBuilder,每次x次迭代我都想清空它并从一个空的StringBuilder开始,但我在留档中看不到任何类似于. NET清除字符串生成器的方法,只是删除方法似乎过于复杂。

那么在Java中清理StringBuilder的最佳方法是什么?

661799 次浏览

两种工作方式:

  1. 使用stringBuilderObj.setLength(0)
  2. 使用new StringBuilder()分配一个新对象,而不是清除缓冲区。请注意,对于性能关键的代码路径,这种方法可能比基于setLength的方法慢得多(因为需要分配具有新缓冲区的新对象,旧对象才有资格进行GC等)。

delete并不复杂:

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

你也可以这样做:

myStringBuilder.setLength(0);

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

如果你事先知道StringBuilder的预期容量,那么每次创建一个新的StringBuilder应该和设置一个新长度一样快。它还将有助于垃圾收集器,因为每个StringBuilder的寿命相对较短,gc已为此进行了优化。

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

如果您查看StringBuilder或StringBuffer的源代码,setL的()调用只是重置字符数组的索引值。使用setL的IMHO方法总是比新的分配更快。他们应该将方法命名为“清除”或“重置”,这样会更清晰。

如果性能是主要问题,那么讽刺的是,在我看来,Java构造来格式化缓冲区的文本,在CPU上比分配/重新分配/垃圾回收机制消耗更多的时间……嗯,可能不是GC(垃圾回收机制),这取决于你创建和丢弃了多少构建器。

但是简单地将复合字符串("Hello World of " + 6E9 + " earthlings.")附加到缓冲区可能会使整个事情变得无关紧要。

而且,实际上,如果涉及StringBuilder的实例,则内容比简单的String str = "Hi";复杂和/或更长(没关系,Java可能在后台使用构建器)。

就个人而言,我尽量不滥用GC。因此,如果它在快速启动的场景中会被大量使用-例如,编写调试输出消息-我只是假设在其他地方声明它并将其归零以供重用。

class MyLogger {
StringBuilder strBldr = new StringBuilder(256);


public void logMsg( String stuff, SomeLogWriterClass log ) {


// zero out strBldr's internal index count, not every
// index in strBldr's internal buffer
strBldr.setLength(0);


// ... append status level
strBldr.append("Info");


// ... append ' ' followed by timestamp
// assuming getTimestamp() returns a String
strBldr.append(' ').append(getTimestamp());


// ... append ':' followed by user message
strBldr.append(':').append(msg);


log.write(strBldr.toString());
}
}

您应该使用sb.delete(0, sb.length())sb.setLength(0)而不是创建新的StringBuilder()。

有关性能,请参阅此相关帖子:在循环中重用StringBuilder更好吗?

StringBuilder s = new StringBuilder();
s.append("a");
s.append("a");
// System.out.print(s); is return "aa"
s.delete(0, s.length());
System.out.print(s.length()); // is return 0

是最简单的方法。

我认为这里的许多答案可能缺少StringBuilder.delete(int start, [int] end)中包含的质量方法。我知道这是一个迟到的回复;然而,这应该被告知(并更彻底地解释)。

假设您有一个StringBuilder表-您希望在整个程序中动态修改它(我现在正在处理的一个表就是这样做的),例如。

StringBuilder table = new StringBuilder();

如果您正在循环遍历该方法并更改内容,使用内容,然后希望丢弃内容以“清理”StringBuilder以进行下一次迭代,您可以删除它的内容,例如:

table.delete(int start, int end).

开始和结束是您要删除的字符的索引。不知道字符的长度并想删除整个内容?

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

StringBuilders,如前所述,在频繁更改时需要大量开销(并且可能导致线程方面的安全问题);因此,使用StringBuffer-与StringBuilder相同(除了少数例外)-如果您的StringBuilder用于与用户交互。

我会投票给sb.setLength(0);,不仅因为它是一个函数调用,而且因为它不会将数组复制到另一个数组中就像sb.delete(0, builder.length());一样。它只是将剩余的字符填充为0并将长度变量设置为新长度。

您可以查看它们的实现来验证我从这里setLength函数和delete0函数的观点。