为什么在StringBuilder构造函数100X中使用连接比调用append()更快?

时间:2015-01-14 22:36:29

标签: java performance stringbuilder

我偶然发现了与StringBuilder的{​​{1}}方法相关的奇怪性能问题。我注意到似乎是一个愚蠢的错误 - 使用append构造函数时的字符串连接(这甚至在NetBeans IDE中显示为警告)。

版本1

StringBuilder

在运行时期间创建了数百万个这样的对象,所以我想通过进行以下更改,它会提供一些加速:

版本2

int hash = -1;     //lazily computed, also present in Version 2
int blockID = ...  //0 to 1000, also present in Version 2
int threadID = ... //0 to 1000, also present in Version 2
boolean hashed = false;       //also present in Version 2

@Override
public int hashCode(){
    if(!hashed){
        StringBuilder s = new StringBuilder(blockID+":"+threadID);
        hash = s.toString().hashCode();
        hashed= true;
    }

    return hash;
}

错误!事实证明,版本2实际上比版本1慢100倍。为什么???

其他信息

我正在编译Java 6(客户需求),我正在使用Oracle的JVM。

我的性能测试涉及创建一百万个这些对象并将它们放入HashMap中。使用版本1需要半秒钟,但使用版本2需要几乎50秒。

2 个答案:

答案 0 :(得分:14)

因为您无意中设置了StringBuilder的初始容量,而不是将blockID附加到其中。请参阅constructor documentation here

  

public StringBuilder(int capacity)

     

构造一个没有的字符串生成器   其中的字符和容量指定的初始容量   参数。

请改为尝试:

StringBuilder s = new StringBuilder(9);
s.append(blockID).append(':').append(threadID);

答案 1 :(得分:1)

你需要检查你的测试,因为你的第一个案例确实在做。

public int hashCode(){
    if(!hashed){
        StringBuilder s = new StringBuilder(
                  new StringBuilder(blockID).append(":").append(threadID).toString());
        hash = s.toString().hashCode();
        hashed= true;
    }

    return hash;
}

换句话说,它在第二种情况下做的更多,所以它会更慢。

简而言之,我怀疑你的测试是错误的,而不是你的表现更好。