Java 循环后清除字符串缓冲区/生成器

Java 循环后清除字符串缓冲区/生成器,java,string,buffer,Java,String,Buffer,如何在循环后清除Java中的字符串缓冲区,以便下一次迭代使用清除字符串缓冲区?一个选项是使用delete方法,如下所示: StringBuffer sb = new StringBuffer(); for (int n = 0; n < 10; n++) { sb.append("a"); // This will clear the buffer sb.delete(0, sb.length()); } 有关更多信息,请参阅:我建议为每个迭代创建一个新的String

如何在循环后清除Java中的字符串缓冲区,以便下一次迭代使用清除字符串缓冲区?

一个选项是使用delete方法,如下所示:

StringBuffer sb = new StringBuffer();
for (int n = 0; n < 10; n++) {
   sb.append("a");

   // This will clear the buffer
   sb.delete(0, sb.length());
}

有关更多信息,请参阅:

我建议为每个迭代创建一个新的
StringBuffer
(甚至更好)。性能差异实际上可以忽略不计,但您的代码将更短、更简单。

重用
StringBuffer
的最简单方法是使用方法
setLength()

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

你可能有这样的情况

StringBuffer sb = new StringBuffer("HelloWorld");
// after many iterations and manipulations
sb.setLength(0);
// reuse sb

我认为这段代码更快。

您有两种选择:

或使用:

sb.setLength(0);  // It will just discard the previous data, which will be garbage collected later.  
或使用:

sb.delete(0, sb.length());  // A bit slower as it is used to delete sub sequence.  

避免在循环中声明
StringBuffer
StringBuilder
对象,否则每次迭代都会创建新对象。创建对象需要系统资源、空间和时间。所以从长远来看,如果可能的话,避免在循环中声明它们。

这已经是一个很好的答案了。只需添加StringBuffer和StringBuild性能差异的基准测试结果,在循环中使用新实例或在循环中使用setLength(0)

总结是:在一个大循环中

  • StringBuilder比StringBuffer快得多
  • 在循环中创建新的StringBuilder实例没有 与setLength(0)的差异。(与创建新实例相比,setLength(0)的优势非常小。)
  • 通过在循环中创建新实例,StringBuffer比StringBuilder慢
  • StringBuffer的setLength(0)比在循环中创建新实例慢得多
非常简单的基准测试(我只是手动更改了代码并进行了不同的测试):

公共类StringBuilderSpeed{
公共静态最终字符ch[]=新字符[]{'a','b','c','d','e','f','g','h','i'};
公共静态void main(字符串a[]{
int loopTime=9999999;
long startTime=System.currentTimeMillis();
StringBuilder sb=新的StringBuilder();
for(int i=0;i
}

循环中的新StringBuilder实例: 时间成本:3693386236243742

StringBuilder设置长度: 时间成本:3465342135573408

循环中的新StringBuffer实例: 时间成本:832783248284

StringBuffer设置长度 时间成本:228782301722894

同样,StringBuilder setLength确保我的labtop不会遇到使用如此长的StringBuffer setLength时出现问题:-) 时间成本:3448

public void clear(StringBuilder s) {
    s.setLength(0);
}
用法:

StringBuilder v = new StringBuilder();
clear(v);

为了可读性,我认为这是最好的解决方案。

我使用下面的代码来存储密码,以便进行临时处理,如正则表达式匹配,并在完成后将其清除。通常的删除方法不会重置所有字符,这不适合我。这个代码满足了我的要求

公共静态无效清除(StringBuilder值){
for(int i=0,len=value.length();i
稍微少一点垃圾的东西就是在循环中声明StringBuffer。啊,我认为sb.setLength(0);比在循环中声明更干净、更高效。您的解决方案与使用StringBuffer的性能优势背道而驰……我认为性能优势来自字符串的可变性,而不是保存实例化。下面是1e8迭代的快速测试:内部循环(2.97s):,外部循环(2.87s):说到性能:除非您的代码是在多线程场景中访问的,否则您应该使用StringBuilder而不是StringBuffer——请参阅javadoc:“在可能的情况下,建议优先使用该类而不是StringBuffer,因为在大多数实现中它会更快”。在外部创建SB的唯一好处是不会丢失它的内部(可能很长)字符[]。如果在第一个迭代器中它足够大,第二个循环将不需要调整任何字符[].但为了获得优势,“清晰方法”“必须保留内部数组的大小。setLength会这样做,但它也会将SB中所有未使用的字符设置为\u0000,因此,仅创建一个具有良好初始容量的新SB的性能较差。在循环内声明更好。另一个问题:为什么只在循环的一次迭代中使用SB?还有其他内部迭代吗?如果您只是想做A+B+C+D(Java编译器将在内部使用SB),那么SB是不值得的。如果您想有条件地添加字符串的一部分,它会很有帮助,但其他方面。。。只需使用“+”@MMahmoud,在代码示例中,它应该是
setLength
而不是
setLength
。当我看到setLength代码源代码时,它是如何工作的()这里的计数将始终大于newLength(0)?这将有性能问题。它会在每次之后创建一个新对象iteration@AdityaSingh这是一个完全合理的方法。不要在没有证据的情况下假设绩效问题。基于对正在发生的事情的理解来假设事情是智力的基础。如果你有任何证据表明绩效存在差异,请分享。(我也很高兴看到Java主要使用的统计数据,以及“主要”的定义)众所周知,分配(Java中的新关键字)比仅仅更改同一对象的某些字段更昂贵。对于“大部分”,你可以高度重放,有超过15亿的Android设备,都使用Java。我同意在某些情况下,代码可读性比性能更重要,但在这种情况下,它只是一行代码!您可以运行一个基准测试来证明分配和
public class StringBuilderSpeed {
public static final char ch[] = new char[]{'a','b','c','d','e','f','g','h','i'};

public static void main(String a[]){
    int loopTime = 99999999;
    long startTime = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for(int i = 0 ; i < loopTime; i++){
        for(char c : ch){
            sb.append(c);
        }
        sb.setLength(0);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Time cost: " + (endTime - startTime));
}
public void clear(StringBuilder s) {
    s.setLength(0);
}
StringBuilder v = new StringBuilder();
clear(v);