如何清除或清空StringBuilder?

Han*_*son 598 java stringbuilder

我在一个循环中使用一个StringBuilder,每个x迭代我想要清空它并以空的开头StringBuilder,但是在文档中我看不到任何类似于.NET StringBuilder.Clear的方法,只是看起来像删除方法过于复杂.

那么StringBuilder用Java 清理一个最好的方法是什么?

Mar*_*din 711

两种工作方式:

  1. 使用stringBuilderObj.setLength(0).
  2. 分配新的new StringBuilder()而不是清除缓冲区.

  • 不,它不那么便宜!你怎么能这样说?假设您有一个容量为1000个字符的缓冲区.然后你处理它(为GC工作)并创建一个新的(为分配器工作).将文本长度设置为零(几乎没有CPU工作)并重用相同的缓冲区要快得多. (279认同)
  • @Marcus,在你提供的链接中,setLength(0)不会像你说的那样迭代,只有当新长度大于used-char计数时才会进行迭代(不能发生0长度) .为了性能,似乎setLength(0)是最好的,它似乎也是清空缓冲区的一个非常明确的含义. (81认同)
  • @Marcus你应该更新你的答案. (20认同)
  • @Sulthan:哦,迟到了这个答案:我在考虑StringBuffer.delete(idx,len).另一方面,执行setLength需要它迭代整个缓冲区并使每个字符为空(例如http://kickjava.com/src/java/lang/AbstractStringBuilder.java.htm).根据缓冲区的大小,这也可能很昂贵.另一方面,除非是优秀的代码,否则请选择看起来最清晰的内容,不要花时间进行微优化. (14认同)
  • 如果您害怕未来的开发人员不理解,您可以发表一些评论 (10认同)
  • @ cafebabe1991仔细阅读源代码:`if(count <newLength)`,但如果`newLength`为0则永远不会发生. (7认同)
  • 在Android上确认.`setLength(0)`的速度是`new StringBuilder(200)`的两倍.使用no-arg构造函数没有任何区别,可能是因为我只需要构建短字符串. (2认同)
  • 我了解您的意见。就是说,这不是内存泄漏,这是所有三种姐妹语言(C#,C ++,Java)中每个连续容器共享的有据可查的行为,其中有std :: vector和ArrayList,StringBuilder以及其他所有内容当更改长度时,自然增长并连续分配的资源将不会重新分配。这不能称为内存泄漏,它有充分的记录,并且可以通过给您同时提供size / length()和Capacity()来完美地访问代码。最重要的是,如果您要的是trimToSize函数,以确保将其回收 (2认同)

Jör*_*ann 291

基本上有两种选择,setLength(0)用于重置StringBuilder或在每次迭代中创建一个新的StringBuilder.根据用途,两者都有利弊.

如果您事先知道StringBuilder的预期容量,则每次创建一个新容量应该与设置新长度一样快.它还将帮助垃圾收集器,因为每个StringBuilder都会相对较短,并且gc已针对此进行了优化.

当您不知道容量时,重用相同的StringBuilder可能会更快.每次超出附加时的容量时,都必须分配新的后备阵列,并且必须复制先前的内容.通过重用相同的StringBuilder,它将在一些迭代后达到所需的容量,之后将不再进行任何复制.


krt*_*tek 71

delete 并不过分复杂:

myStringBuilder.delete(0, myStringBuilder.length());
Run Code Online (Sandbox Code Playgroud)

你也可以这样做:

myStringBuilder.setLength(0);
Run Code Online (Sandbox Code Playgroud)

  • 这就是我添加setLength(0)版本的原因,它应该更快.但可能新的分配会更快. (4认同)
  • "setLength"替代方案很有意思,谢谢. (4认同)
  • 考虑将stringbuilder对象作为输出参数传递给函数,然后新的分配不是一个选项. (3认同)

Jav*_*ann 30

如果查看StringBuilder或StringBuffer的源代码,setLength()调用只会重置字符数组的索引值.使用setLength方法的IMHO总是比新的分配更快.他们应该将方法命名为"clear"或"reset",以便更清楚.

  • @FrankHarper:仅当你扩展字符串时.如果你缩小它,Javamann是正确的. (4认同)

Ahm*_*azy 18

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

你可以看看到他们实现从验证我的观点在这里setLength功能和delete0作用.

  • 不要挑字。只需阅读答案即可明白我的观点。 (3认同)
  • setLength 也会导致内存泄漏,但你会发现为时已晚。setLength 除了将长度设置为零之外什么也不做。剩余的分配仍然存在。 (2认同)

小智 7

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

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


Dev*_*ght 5

如果性能是主要关注点,那么讽刺的是,在我看来,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());
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您是通过运算符+连接字符串来向我们展示一些东西还是只是代码味道? (4认同)

jav*_*oid 5

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
Run Code Online (Sandbox Code Playgroud)

这是最简单的方法。

  • 为什么你认为这是最好的方法?对我来说,它看起来比 setLength(0) 变体更难看。 (9认同)

Tho*_*mas 5

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

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

StringBuilder table = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

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

table.delete(int start, int end). 
Run Code Online (Sandbox Code Playgroud)

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

table.delete(0, table.length());
Run Code Online (Sandbox Code Playgroud)

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