/**
* Holds cached entrySet(). Note that AbstractMap fields are used
* for keySet() and values().
*/
transient Set<Map.Entry<K,V>> entrySet;
我在javaHashmap中发现了一件奇怪的事情。我在hashmap源代码和AbstractMap代码中找不到创建和操作entrySet实例的代码。但是当我把key-value放在hashmap中时,entrySet得到了新的值。这很奇怪。
所以我的问题是:
entrySet如何获取新值,何时获取其实例?
为了更清楚,我在IDE中添加了调试代码,发现在我第一次调用这个集合之前,它已经不是空的,并且充满了元素。
这个entrySet
字段是在调用entrySet()
方法时设置的。请参阅OpenJDK 8中entrySet()
的源代码:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
还要检查链接源代码中方法正下方的内部EntrySet
类。
entrySet如何获取新值,何时获取其实例?
entrySet的实例是在第一次调用Map. entrySet()时创建的。
我们可以在HashMap的源代码中看到:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
public final Iterator<Map.Entry<K,V>> iterator() {
return new EntryIterator();
}
public final boolean contains(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Node<K,V> candidate = getNode(hash(key), key);
return candidate != null && candidate.equals(e);
}
public final boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>) o;
Object key = e.getKey();
Object value = e.getValue();
return removeNode(hash(key), key, value, true, true) != null;
}
return false;
}
public final Spliterator<Map.Entry<K,V>> spliterator() {
return new EntrySpliterator<>(HashMap.this, 0, -1, 0, 0);
}
public final void forEach(Consumer<? super Map.Entry<K,V>> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
}
EntrySet
类只是作用于内部HashMap
的一组方法。因此,EntrySet
不包含任何信息,它只是对HashMap
的数据的视图。
Map. entrySet
只会让您将Map
视为Set
Java内部类有两个(或更多)this
(假设它们不是静态上下文中的本地类)。在Python,按照惯例,self
用于this
。(我Python没做那么多。)所以内部类的任何方法都会隐藏外部的self。你必须使用不同的名称,当然每次使用它们时都要显式。在Java,如果你不显式,它会选择合适的this
(在角落情况下可能会很奇怪)。