HashMap与LinkedHashMap在值迭代中的性能()
HashMap
和LinkedHashMap
之间是否存在遍历values()
函数的性能差异?
我认为LinkedHashMap
在遍历中必须更快,因为它的Iterator
有一个优秀的nextEntry
实现
原因如下:
让我们从values
实现中一步一步走。
values
的HashMap
实现是这样的:
public Collection values() { Collection vs = values; return (vs != null ? vs : (values = new Values())); }
LinkedHashMap
从HashMap
扩展并inheritance相同的实现。
不同之处在于两者中Values
的Iterator
实现。
对于HashMap
它从java.util.HashMap.HashIterator
扩展
private final class ValueIterator extends HashIterator { public V next() { return nextEntry().value; } }
但对于LinkedHashMap
它扩展自java.util.LinkedHashMap.LinkedHashIterator
private class ValueIterator extends LinkedHashIterator { public V next() { return nextEntry().value; } }
所以差异基本上归结为nextEntry
实现。
对于LinkedHashMap
它只是调用e.after,其中e是Entry
,但是对于HashMap
,遍历Entry[]
数组以查找下一个下一个涉及到一些工作。
更新 : HashMap
nextEntry()
代码
final Entry nextEntry() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); Entry e = next; if (e == null) throw new NoSuchElementException(); if ((next = e.next) == null) { Entry[] t = table; while (index < t.length && (next = t[index++]) == null) ; } current = e; return e; }
Entry []不是连续的商店。 (两者之间可能存在空值)。 如果您查看上面的代码,它的作用是指向current旁边,并通过迭代Entry []找到下一个代码。
但我认为这种性能提升将以插入成本为代价。 在两个类中查看addEntry
方法作为练习。
我写了一个小的分析程序,创建了100万个键(Integer)和Boolean.TRUE,重复了100次。 找到以下内容:
HashMap:- Create: 3.7sec Iterate: 1.1sec Access: 1.5sec Total: 6.2sec LinkedHashMap:- Create: 4.7sec (30% slower) Iterate: 0.5sec (50% faster) Access: 0.8sec (50% faster) Total : 6.0sec
垃圾收集没有这样做有点污染数字,但我认为LinkedHashMap优于HashMap,我将在未来的代码中使用它。
这几乎没关系。 问题是:你需要什么。 如果元素的顺序是相关的,则必须使用LinkedHashMap
。 否则你只是不需要它,所以使用HashMap
。
最好的建议是“不要害怕尝试”,但我很确定它们非常相似。 值集的getter是O(1),每个迭代器步骤也是如此。 通过链表重复迭代与遍历散列桶一样微不足道,在链表的favpr中可能存在小的边缘。
我尝试了一个UnitTest,迭代值()10000次,毫秒:806对902.它几乎是一样的。
是的,在HashMap
和LinkedHashMap
所有迭代中都会有相同的性能差异: HashMap
需要的时间与条目数加上哈希表的大小成正比,而LinkedHashMap
只需要与条目数成比例的时间。