Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 什么样的StringBuffer new()或delete(0,sb.length())更有效?_Java_Instance_Stringbuffer_Performance - Fatal编程技术网

Java 什么样的StringBuffer new()或delete(0,sb.length())更有效?

Java 什么样的StringBuffer new()或delete(0,sb.length())更有效?,java,instance,stringbuffer,performance,Java,Instance,Stringbuffer,Performance,经常有人认为避免创建对象(尤其是在循环中)被认为是良好的做法 那么,关于StringBuffer,什么是最有效的 StringBuffer sb = new StringBuffer(); ObjectInputStream ois = ...; for (int i=0;i<1000;i++) { for (j=0;i<10;j++) { sb.append(ois.readUTF()); } ... // Which opti

经常有人认为避免创建对象(尤其是在循环中)被认为是良好的做法

那么,关于
StringBuffer
,什么是最有效的

StringBuffer sb = new StringBuffer();
ObjectInputStream ois = ...;

for (int i=0;i<1000;i++) {

    for (j=0;i<10;j++) {
        sb.append(ois.readUTF());
    }
    ...

    // Which option is the most efficient? 
    sb = new StringBuffer(); // new StringBuffer instance?
    sb.delete(0,sb.length()); // or deleting content?

}
StringBuffer sb=new StringBuffer();
ObjectInputStream ois=。。。;

for(int i=0;i首先
StringBuffer
是线程安全的,与
StringBuilder
相比,它的性能会很差。StringBuilder不是线程安全的,但因此速度更快。最后,我更喜欢使用将长度设置为0

这与
.delete(…)
类似,只是您并不真正关心长度。由于它不需要“删除”任何内容,因此可能会快一点。创建新的
StringBuilder
(或StringBuffer)任何时候你看到
new
Java正在创建一个新对象并将其放在堆上


注意:在研究了
.delete
.setLength
的实现之后,
.delete
将长度设置为0,并且
。setLength
将每件事都设置为
'\0'
,这样您就可以在
上获得一点胜利。delete
删除方法是这样实现的:

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;
}
public AbstractStringBuilder删除(int开始,int结束){
如果(开始<0)
抛出新StringIndexOutOfBoundsException(开始);
如果(结束>计数)
结束=计数;
如果(开始>结束)
抛出新的StringIndexOutOfBoundsException();
int len=结束-开始;
如果(len>0){
System.arraycopy(值,开始+长度,值,开始,计数结束);
计数-=len;
}
归还这个;
}

正如您所见,它不会遍历数组。

只是为了放大前面的注释:

从源代码看,
delete
()总是调用
System.arraycopy
(),但如果参数为(0,count),它将调用长度为零的
arraycopy
(),这可能没有任何效果。嗯,这应该优化,因为我打赌这是最常见的情况,但没关系

另一方面,使用
setLength
(),如果需要,调用将通过调用
ensureCapacityInternal
()(另一种非常常见的情况,应该在IMHO中进行优化),增加StringBuilder的容量,然后按照
delete
()的方式截断长度

最终,这两种方法都将
count
设置为零

在这种情况下,两个调用都不会进行任何迭代。都会进行不必要的函数调用。但是,ensureCapacityInternal()是一个非常简单的私有方法,它会邀请编译器在几乎不存在的情况下对其进行优化,因此
setLength
()的效率可能会稍高一些

我非常怀疑创建一个新的StringBuilder实例是否能像简单地将
count
设置为零那样有效,但我认为编译器可能会识别所涉及的模式,并将重复的实例化转换为对
setLength
的重复调用(0).但最好的情况是,这是一个清洗。你要依靠编译器来识别这种情况


执行摘要:setLength(0)是最有效的。为了获得最高效率,请在创建StringBuilder时在StringBuilder中预先分配缓冲空间。

您在探查器中测试过它吗?结果如何?另请参见您认为的
系统。arraycopy
有什么作用???@Mike我不确定您的意思是
len
将为0。它是从
结束-开始
计算出来的will
sb.length()-0
。你想说的
count end
将是0,这是真的。但是通常你不计算O(n)只有一组参数。@Amir,很抱歉,我认为我没有做任何重要的工作是对的,但为什么我错了。当
start
为0,而
end
count
aka
this.length()
,那么你最终会做
System.arraycopy(value,count,value,0,0)
。最后一个0表示它正在将0字节从索引计数复制到索引0。我已经查看了源代码。在本例中,是arraycopy()只会返回。您所做的只是浪费函数调用的开销。如果
StringBuilder
分配了一个非常大的内部缓冲区,这是因为早期循环迭代生成了非常大的字符串而浪费的,而以后的迭代则不会,那么您可能会在不必要的情况下浪费更长的时间,但在其他情况下,保持t缓冲区是一个净胜利,因为如果以后的迭代产生的字符串与以前的迭代几乎相同大小,则可以避免一些缓冲区副本。
delete
不是O(N)当删除清除全部内容时。这是真的,我正在更新我的答案。但只有当len==count时,如果删除所有内容,这才是真的。
setLength
不会将所有内容都设置为“\0”。只有当新大小>为当前大小并且仅用于扩展的内部缓冲区部分时。令人惊讶的是,
StringBuilder.delete()
StringBuilder.setLength(0)
每JMH快26%。它只是告诉您,您无法通过查看代码来确定什么更快。
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;
}