所有
任何人都可以让我知道两者之间的性能问题究竟是什么?站点:CodeRanch提供了使用keySet()和get()时所需的内部调用的简要概述。但是如果有人能够在使用keySet()和get()方法时提供有关流的确切细节,那将会很棒。这有助于我更好地理解性能问题。
答案 0 :(得分:68)
最常见的情况是,使用entrySet优于keySet是在迭代Map中的所有键/值对时。
这更有效:
for (Map.Entry entry : map.entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
}
比:
for (Object key : map.keySet()) {
Object value = map.get(key);
}
因为在第二种情况下,对于keySet中的每个键,调用map.get()
方法,在HashMap的情况下,需要hashCode()
和equals()
方法。评估关键对象以便找到关联值*。在第一种情况下,额外的工作被消除。
编辑:如果你考虑一个TreeMap,更糟糕的是,对get的调用是O(log2(n)),即will的比较器可能需要运行log2(n)次(n = Map的大小) )在找到相关值之前。
*某些Map实现具有内部优化功能,可在调用hashCode()
和equals()
之前检查对象的身份。
答案 1 :(得分:68)
首先,这完全取决于您使用的是哪种类型的地图。但是由于JavaRanch线程谈论HashMap,我将假设这是你所指的实现。我们还假设您正在讨论Sun / Oracle的标准API实现。
其次,如果您在迭代哈希映射时关注性能,我建议您查看LinkedHashMap
。来自文档:
迭代LinkedHashMap的集合视图需要与地图大小成比例的时间,无论其容量如何。对HashMap的迭代可能更昂贵,需要与其容量成比例的时间。
此实现的源代码可用。实现基本上只返回一个新的HashMap.EntrySet
。一个看起来像这样的类:
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return newEntryIterator(); // returns a HashIterator...
}
// ...
}
和HashIterator
看起来像
private abstract class HashIterator<E> implements Iterator<E> {
Entry<K,V> next; // next entry to return
int expectedModCount; // For fast-fail
int index; // current slot
Entry<K,V> current; // current entry
HashIterator() {
expectedModCount = modCount;
if (size > 0) { // advance to first entry
Entry[] t = table;
while (index < t.length && (next = t[index++]) == null)
;
}
}
final Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> 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;
}
// ...
}
所以你有它...这就是代码,它规定了迭代entrySet时会发生什么。它遍历整个数组,这与地图容量一样长。
首先,您需要掌握这组键。这需要时间与地图的容量成比例(而不是LinkedHashMap的 size )。完成此操作后,您为每个密钥调用get()
一次。当然,在一般情况下,使用一个好的hashCode实现,这需要恒定的时间。但是,它将不可避免地要求进行大量.hashCode
和.equals
次呼叫,这显然比只进行entry.value()
呼叫需要更多时间。
答案 2 :(得分:14)
Here is the link to an article比较entrySet()
,keySet()
和values()
的效果,以及有关何时使用每种方法的建议。
显然,keySet()
的使用比entrySet()
更快(除了更方便),只要您不需要Map.get()
值。