【问题标题】:Is there a collections addAll utility method that will ensure that the underlying data structure of the collection is only resized at most once?是否有一个集合 addAll 实用程序方法可以确保集合的底层数据结构最多只调整一次大小?
【发布时间】:2012-04-09 14:29:58
【问题描述】:

java.util.Collections 中 addAll 方法的实现只是简单地遍历源集合,并为源集合中的每个元素调用接收集合的 add 方法。

因此,如果接收集合的容量很小并且我们正在向其中添加许多元素,则可能会多次调整接收集合的底层数据结构的大小。每次调整大小都是 O(n) 操作。

似乎应该存在一个好的集合 addAll 方法,该方法将检查我们将添加的元素数量并在开始时设置一次接收集合的容量(如有必要)。这样的实用方法是否存在?如果没有,为什么不呢?

澄清:我意识到有特定于实现的 addAll 方法(如在 ArrayList 中)具有这种所需的行为。我想知道是否有 Collection 实用程序类可以让我以一种适用于所有 Collection 实现类的方式获得这种行为。

【问题讨论】:

    标签: java collections


    【解决方案1】:

    您具体说的是哪个系列?我看到了,例如ArrayList 执行以下操作:

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacity(size + numNew);
        System.arraycopy(a, 0, elementData, size, numNew);
        //...
    }
    

    这似乎正是您想要的行为。

    【讨论】:

    • 是的,这正是我要说的。这适用于 ArrayList,但我想知道是否有一个 Collections 实用程序类将有一个 addAll 方法,该方法只调整一次大小,适用于所有 Collections。从答案来看,似乎不存在这样的实用方法,因为 Collection 实现之间存在很大差异。
    【解决方案2】:

    这样的实用方法不能用于泛型Collection,因为必要的方法ensureCapacity(int) 不在任何接口中,而仅在对此有一些好处的实现上。目前是ArrayListBitSetVectorArrayListVector 都调整了 addAll 方法。 BitSet 完全不同:-)

    【讨论】:

      【解决方案3】:

      这取决于具体的集合实现。

      例如,对于 ArrayList,它将增加一次数组大小。而且通常它会加倍大小,因此执行 10 次调用并不总是需要创建 10 个新数组。

      但对于 LinkedList,它只需要附加到每个元素的末尾。可以很快完成的事情。

      【讨论】:

        【解决方案4】:

        我对你的澄清感到困惑,因为Collection.addAll 你似乎要求的方法。

        【讨论】:

        • 没有。如果将大量对象添加到初始容量较小的集合中,java.util.Collections.addAll 最终可能会多次调整底层数据结构的大小。这是我试图避免的行为。
        • 我觉得你还是误会了。我说的是Collection.addAll,而不是Collections.addAll,一方面。这让实现类可以做它知道如何做的最好的事情。你将如何变得更好?
        猜你喜欢
        • 2011-02-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        • 2018-12-11
        • 2011-09-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多