为什么列表大小小于COPY_THRESHOLD意味着它是一个ArrayList?

huangapple go评论60阅读模式
英文:

Why a list size lower than COPY_THRESHOLD means it is a arraylist?

问题

java.util.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());
            }
        }
    }

如果src列表的大小小于COPY_THRESHOLD,即 srcSize < COPY_THRESHOLD,那么它是一个ArrayList。我不知道为什么。

英文:

In package java.util.Collections, here is the source code about copy function:

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

        if (srcSize &lt; COPY_THRESHOLD ||
            (src instanceof RandomAccess &amp;&amp; dest instanceof RandomAccess)) {
            for (int i=0; i&lt;srcSize; i++)
                dest.set(i, src.get(i));
        } else {
            ListIterator&lt;? super T&gt; di=dest.listIterator();
            ListIterator&lt;? extends T&gt; si=src.listIterator();
            for (int i=0; i&lt;srcSize; i++) {
                di.next();
                di.set(si.next());
            }
        }
    }

And if the src list size lower than COPY_THRESHOLD srcSize &lt; COPY_THRESHOLD,then it is a arraylist.I don't know why.

答案1

得分: 2

这是一个诡计性的问题 - 它不会假设这是一个数组列表。如果它这样做了,你会知道,因为它可能会将其强制转换为 ArrayList

相反,原因很可能是效率。List 的两种最常见的变体是 ArrayListLinkedListArrayList 支持随机访问,因此访问任何单独的元素都同样快速,但 LinkedList不是,所以距离前面的任何元素越远,所需时间越长。

如果列表支持随机访问(这意味着访问任何元素的效率都与访问其他任何元素一样),那么将列表 A 复制到列表 B 的最快方法很可能是简单地使用 get()set() 来操作相关索引。这就是条件 (src instanceof RandomAccess && dest instanceof RandomAccess) 所检查的。

如果列表不是随机访问的,例如链表或其他类型的列表,那么通过 get()set() 在中间访问元素很可能效率低下。因此,Java 使用迭代器,逐个复制元素。这就是条件的 else 块。

问题在于,创建列表迭代器并使用它们进行迭代需要开销时间,如果你使用原始的 int,则不需要花费这些时间。如果你的链表足够小 - 也就是说,你需要复制的所有项都靠近前面 - 那么使用 get()set() 可能仍然比使用迭代器更快。这就是条件 srcSize < COPY_THRESHOLD 所检查的。可以假设 COPY_THRESHOLD 是一个常数,根据 Java 开发人员基于实验确定的,以便始终选择最快的方法。

英文:

It's a trick question - it doesn't assume it's an array list. You would know if it did, because it would do a cast to ArrayList, probably.

Instead, the reason is likely efficiency. The two most common varieties of List are ArrayList and LinkedList; ArrayList is random-access, so getting to any individual element is equally fast, but LinkedList is not, so the further from the front any element is, the longer it takes.

If the list is random-access (which is to say, accessing any element is as efficient as accessing any other), then it makes sense that the fastest way to copy list A over to list B would be to simply get() and set() the relevant indices. This is what the condition (src instanceof RandomAccess &amp;&amp; dest instanceof RandomAccess) checks.

If a list is not random-access, so is a linked list or some other type of list, then accessing elements in the middle via get() and set() is likely to be inefficient. So, Java uses iterators instead, copying elements one at a time. This is the else block of the conditional.

The problem with that, is that creating the list iterators, and iterating with them, requires overhead time that you wouldn't need to spend if you were using a primitive int. If your linked list is small enough - so, all the items you need to copy are close to the front - then it's probably still faster to use get() and set() than it is to use iterators. This is what the condition srcSize &lt; COPY_THRESHOLD checks. Presumably, COPY_THRESHOLD is a constant that's been determined by the Java developers based on experimentation, so that the quickest approach is always chosen.

huangapple
  • 本文由 发表于 2020年8月24日 11:20:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63554294.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定