每当调用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
?
谢谢。
答案 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}}复制时不需要任何额外的临时内存。