addAll方法的问题

时间:2016-07-30 07:50:00

标签: java

每当调用Collection#addAll时,它都会创建参数列表的副本,然后将其附加到调用addAll的集合中。

以下是案例I的代码:

        if (parentData != 0) {
            if (nodeParentMap.get(parentData) != null) {
                nodeParentMap.put(newNodeData, parentData);
                //Creates new Nodes' parent and assigns its next to its parent, in that way I get the parents' linked list
                Node parent = Node.build(parentData);
                parent.next = parentListMap.get(parentData);

                parentListMap.put(newNodeData, parent);
            }
        } else {
            //Code for root
            nodeParentMap.put(newNodeData, parentData);
            parentListMap.put(newNodeData, null);
        }

此处需要N次迭代才能找到Nth parent

以下是案例II的代码:

       if (parentData != 0) {
            if (nodeParentMap.get(parentData) != null) {
                nodeParentMap.put(newNodeData, parentData);

                //Here all the parents of a node are present in arrayList #parents, 
                //so that I can fetch parent in O(1) as I know the index
                ArrayList<Integer> parents = new ArrayList<>();
                parents.add(parentData);
                parents.addAll(parentListMap.get(parentData));

                parentListMap.put(newNodeData, parents);
            }
        } else {
            //Code for root
            nodeParentMap.put(newNodeData, parentData);
            parentListMap.put(newNodeData, new ArrayList<>());
        }

但是在调用ArrayList#addAll的情况下,它会创建传递的列表的副本,然后将其附加到其中。那么,有没有办法通过调用ArrayList#addAll执行System#arrayCopy

谢谢。

1 个答案:

答案 0 :(得分:1)

一般来说,你不应该在乎。除非您运行此代码数百万次,否则差异将无法察觉。如果可能的话,您应尽可能干净地编写代码,并使其显示您的意图。你有性能问题吗?您是否已分析过您的代码,并且分析器向您展示了您是否花费了大量时间来复制数组元素?

测量,不要猜。你需要一种方法来判断是否存在问题。而且你需要一种方法来判断代码更改后它是否已经消失。

如果有如此多的重复数据和如此多的元素复制,您是否可以使用更高效的结构或算法,您是否可以更改算法?例如,您可以使用Google Guava的Iterables.concat()。生成的代码将更短,非常干净地陈述您的意图并且不会复制任何内容 - 基础List将包含对原始数据结构的引用,并且只会懒惰地获取它。请注意,如果这是大规模链接,你实际上并没有帮助自己......

如果毕竟你仍然认为你还需要避免双阵列复制,是什么阻止你做这个?

List<Integer> tempParents = parentListMap.get(parentData);
List<Integer> parents = new ArrayList<>(tempParents.size() + 1);
parents.add(parentData);
for (Integer i : tempParents) {
    parents.add(i);
}

请注意,在性能方面,此代码通常可以与仅调用addAll() 相媲美,因为在ArrayList的addAll()实现的addAll()中实现了&#39;没有迭代,只是在JVM中内化并且高度优化的硬数组复制。因此,上述版本仅对短列表(可能)有用或解决内存问题,而不是性能问题,因为迭代版本在从{{1}}复制时不需要任何额外的临时内存。