为什么java中的Collections的fill(),copy(),reverse()和shuffle()以这种方式实现

Pri*_*shi 7 java collections performance iterator list

根据javadoc ... Collections.fill()编写如下:

public static <T> void fill(List<? super T> list, T obj) {
        int size = list.size();

        if (size < FILL_THRESHOLD || list instanceof RandomAccess) {
            for (int i=0; i<size; i++)
                list.set(i, obj);
        } else {
            ListIterator<? super T> itr = list.listIterator();
            for (int i=0; i<size; i++) {
                itr.next();
                itr.set(obj);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

很容易理解他们为什么不使用listIterator

if (size < FILL_THRESHOLD || list instanceof RandomAccess) 
Run Code Online (Sandbox Code Playgroud)

条件为RandomAccess.但是size < FILL_THRESHOLD上面的使用是什么?

我的意思是使用iteratorfor size>=FILL_THRESHOLD而不是for for 有任何显着的性能优势size < FILL_THRESHOLD吗?

我也看到了Collections.copy()的相同方法:

 public static <T> void copy(List<? super T> dest, List<? extends T> src) {
        int srcSize = src.size();
        if (srcSize > dest.size())
            throw new IndexOutOfBoundsException("Source does not fit in dest");

        if (srcSize < COPY_THRESHOLD ||
            (src instanceof RandomAccess && dest instanceof RandomAccess)) {
            for (int i=0; i<srcSize; i++)
                dest.set(i, src.get(i));
        } else {
            ListIterator<? super T> di=dest.listIterator();
        ListIterator<? extends T> si=src.listIterator();
            for (int i=0; i<srcSize; i++) {
                di.next();
                di.set(si.next());
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

供参考:

 private static final int FILL_THRESHOLD           =   25;

 private static final int COPY_THRESHOLD           =   10;
Run Code Online (Sandbox Code Playgroud)

以下相同的方法:

 public static void reverse(List<?> list)
 public static void shuffle(List<?> list, Random rnd) 
Run Code Online (Sandbox Code Playgroud)

编辑:

我的困惑只是size<FILL_THRESHOLD部分而非RandomAccess

Jac*_*ack 3

我想这是因为通用列表并不意味着是ArrayList. 不能保证设置随机索引是在恒定的O(1)时间内完成的。同时构建迭代器并对其进行操作也有其开销。

总之,对于小型列表,您可以牺牲这样一个事实:使用迭代器可以通过节省创建迭代器本身的开销来降低访问连续元素的复杂性。

这是因为list.set(i, obj)可能会更昂贵,itr.set(obj)但在后者中,您将有管理迭代器的隐含开销。由于复杂度可以是线性的O(n),因此使用list.set(i, obj)更大的列表实际上可能是一个问题。