HashMap与LinkedHashMap在值迭代中的性能()

HashMapLinkedHashMap之间是否存在遍历values()函数的性能差异?

我认为LinkedHashMap在遍历中必须更快,因为它的Iterator有一个优秀的nextEntry实现

原因如下:

让我们从values实现中一步一步走。
valuesHashMap实现是这样的:

  public Collection values() { Collection vs = values; return (vs != null ? vs : (values = new Values())); } 

LinkedHashMapHashMap扩展并inheritance相同的实现。

不同之处在于两者中ValuesIterator实现。

对于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.它几乎是一样的。

是的,在HashMapLinkedHashMap所有迭代中都会有相同的性能差异: HashMap需要的时间与条目数加上哈希表的大小成正比,而LinkedHashMap只需要与条目数成比例的时间。