Java 了解StringUtils.join性能决策

Java 了解StringUtils.join性能决策,java,string,performance,apache-stringutils,Java,String,Performance,Apache Stringutils,我在研究ApacheCommons的StringUtils.join方法的实现时,偶然发现了一行我认为是为了提高性能的代码,但我不明白他们为什么用这些特定的值这样做 以下是实现: public static String join(Object[] array, String separator, int startIndex, int endIndex) { if (array == null) { return null; } if (separato

我在研究ApacheCommons的StringUtils.join方法的实现时,偶然发现了一行我认为是为了提高性能的代码,但我不明白他们为什么用这些特定的值这样做

以下是实现:

public static String join(Object[] array, String separator, int startIndex, int endIndex) {
    if (array == null) {
        return null;
    }
    if (separator == null) {
        separator = EMPTY;
    }

    // endIndex - startIndex > 0:   Len = NofStrings *(len(firstString) + len(separator))
    //           (Assuming that all Strings are roughly equally long)
    int noOfItems = (endIndex - startIndex);
    if (noOfItems <= 0) {
        return EMPTY;
    }

    StringBuilder buf = new StringBuilder(noOfItems * 16); // THE QUESTION'S ABOUT THIS LINE

    for (int i = startIndex; i < endIndex; i++) {
        if (i > startIndex) {
            buf.append(separator);
        }
        if (array[i] != null) {
            buf.append(array[i]);
        }
    }
    return buf.toString();
}
公共静态字符串联接(对象[]数组、字符串分隔符、int-startIndex、int-endIndex){
if(数组==null){
返回null;
}
if(分隔符==null){
分隔符=空;
}
//endIndex-startIndex>0:Len=NofStrings*(Len(第一个字符串)+Len(分隔符))
//(假设所有字符串的长度大致相等)
int noOfItems=(endIndex-startIndex);

如果(noOfItems真的……这不是你在问题中所说的唯一的
16

如果你再研究一下这个定义,你会发现类似的东西

bufSize *= ((array[startIndex] == null ? 16 : array[startIndex].toString().length())
                        + separator.length());  
     //16 will only assigned if Object array at position StartIndex contains null.

        StringBuffer buf = new StringBuffer(bufSize); //if null then default memory allocation for String Buffer will be 16 only.
这里
StringBuffer
将调用构造函数,该构造函数将

     new StringBuffer(int Capacity);
Constructs a string buffer with no characters in it and the specified initial capacity.
如果对象数组包含at index
startIndex
的元素,则默认的备忘分配将是该
对象的
length


谢谢。

16
略微高估了带分隔符的字符串的预期平均大小(可能基于经验/统计数据)

预先分配足够的空间来保存整个结果,可以避免在执行过程中使用更大(大小的两倍)的数组替换备份数组并在元素上进行复制(这是一个O(n)操作)


如果在大多数情况下避免了替换操作,那么高估分配更大数组的成本是值得的,即使高估了一点。

hmm..
StringUtils.join
make
OutOfMemory Exception
在大数组中。。。;
你知道这种情况。

我不知道,但我猜16只是对平均预期大小的猜测。听起来对于我通常需要它的用例来说是正确的。请记住,StringBuilder将在一段时间内完成GC,所以它是否有点太大并不重要。节省调整大小很好,因为调整大小需要复制覆盖整个前一个数组;在最坏的情况下,如果每次调整大小,则性能为o(n^2)。