StringBuilder - 重置或创建新的

时间:2013-09-12 14:18:15

标签: java stringbuilder

我有一个条件,StringBuilder保持存储与大型平面文件(100的MB)中的模式匹配的行。但是在达到条件后,我将StringBuilder varialble的内容写入文本文件。

现在我想知道是否应该通过重置对象来使用相同的变量 - >

stringBuilder.delete(0,stringBuilder.length())

OR

stringBuilder=new StringBuilder();

请提出建议,就性能和OOM问题而言,您认为哪个更好。

8 个答案:

答案 0 :(得分:32)

我认为StringBuilder#delete(start, end)仍然是昂贵的电话,你应该这样做:

stringBuilder.setLength(0);

重置它。


更新:查看source code of StringBuilder看来setLength(int)保留旧缓冲区,最好拨打电话: StringBuilder#trimToSize() 在上面调用 attempts to reduce storage used for the character sequence

之后

这样的事情会更有效率:

stringBuilder.setLength(0); // set length of buffer to 0
stringBuilder.trimToSize(); // trim the underlying buffer

答案 1 :(得分:5)

Imho,我建议使用新的:

stringBuilder = new StringBuilder();

我从来没有听说过StringBuilder中的内存泄漏,但是当你真正推动你永远不知道的限制时。我会每次使用一个新实例来对冲我的赌注。

在最糟糕的情况下,你可能会失去一些效率并且gc得到锻炼,但是你排除了OOM的可能性。

正因为如此,并且为了清楚起见,我个人会采用新方法。

答案 2 :(得分:4)

一个根本区别是sb.delete保留引用,而构造函数则丢失它。

如果您的SB是方法参数,并且应该用于将内容传递回调用者,则必须使用sb.delete。来电者持有原始参考资料。

答案 3 :(得分:2)

两者之间存在更大的差异。第一个保留了删除字符之前的容量(即stringBuilder.capacity()),而第二个创建了一个具有默认容量16的新StringBuilder。当然,您可以将stringBuilder.capacity()传递为构造函数的参数,但重要的是要理解这里的区别。

在任何情况下,我都非常怀疑您会发现这两种变体之间存在显着的性能差异,因此请选择更易读且更易于管理的变量。 ,如果您确定这会导致某种瓶颈,那么当您改变方法时,

答案 4 :(得分:1)

我会用:

 stringBuilder = new StringBuilder();

因为如果你用大量数据填充它,调用stringBuilder.setLength(0);将不会取消分配支持数组,所以你可以看到内存使用率不必要地高。

此外,它更容易阅读和理解。

答案 5 :(得分:1)

理想情况下我们应该使用form.gender.$modelValuegrepcode的StringBuilder类中挖掘一下我会了解以下内容。

创建新对象:

new StringBuilder()

new StringBuilder()创建一个具有初始容量char数组的新对象。 这里的开销:将调用GC来清除旧对象。

使用删除:

/**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

使用长度和TrimToSize:

public AbstractStringBuilder delete(int start, int end) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            end = count;
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        int len = end - start;
        if (len > 0) {
            System.arraycopy(value, start+len, value, start, count-end);
            count -= len;
        }
        return this;
    }

将调用copyOf来自数组类

public static char [] copyOf(char [] original,int newLength){     char [] copy = new char [newLength];     System.arraycopy(原始,0,副本,0,                      Math.min(original.length,newLength));     返回副本; }

现在它还将调用 System.arrayCopy ,这是一种本机方法。 现在,如果你在copyOf中看到我们再创建一个0长度的新charArray, 当我们尝试再次向其添加数据时,它会调用expand ,因为当前长度为0 。 所以我认为最好调用新的StringBuilder()

您可以在grepcode

上看到上述代码

PS:@ user3241961是写的,以防您使用此对象的引用,然后new需要再次设置

答案 6 :(得分:1)

重新创建对象比分配新对象更便宜。它还避免了垃圾收集器的额外工作,因为您只处理一个对象。

更快的方法是:

stringBuilder.setLength(0);

答案 7 :(得分:0)

如果您处于紧密循环中并且在将数据写入文件后将继续返回该循环,则应该重新使用StringBuilder。没有理由不这样做,而且比搅拌GC更好。如果你用C或C ++编写它,你将重新使用缓冲区。

此外,虽然delete(...)方法调用System.arraycopy,但复制的字节数为0,因此它无关紧要。

啊 - 有人提到我有一个setLength(...)方法,这是重用缓冲区的最快方法。