我正在尝试理解HashMap中的entrySet()函数,但我不确定它是如何工作的以及在创建新的EntrySet()时从哪里填充值。
public Set<Map.Entry<K,V>> entrySet() {
return entrySet0();
}
private Set<Map.Entry<K,V>> entrySet0() {
Set<Map.Entry<K,V>> es = entrySet;
return es != null ? es : (entrySet = new EntrySet());
}
答案 0 :(得分:4)
以下是jdk8中的entrySet()的源代码:
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();//get the iterator
}
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()方法时,它返回新的EntrySet(),它是EntrySet的一个实例。这个类有一个iterator()方法,可以用于...循环。并且iterator()方法返回一个迭代器(class:EntryIterator)
第二:我们阅读了最终类EntryIterator的源代码:
final class EntryIterator extends HashIterator implements Iterator<Map.Entry<K,V>> {
public final Map.Entry<K,V> next() { return nextNode(); }
}
从代码中,我们可以看到它实现了next()方法。它返回nextNode();
第三:我们读了nextNode方法的源代码(它在HashIterator类中):
abstract class HashIterator {
Node<K,V> next; // next entry to return
Node<K,V> current; // current entry
int expectedModCount; // for fast-fail
int index; // current slot
HashIterator() { //when new EntryIterator, this will load data first.
expectedModCount = modCount;
Node<K,V>[] t = table;
current = next = null;
index = 0;
if (t != null && size > 0) { // advance to first entry
do {} while (index < t.length && (next = t[index++]) == null);
}
}
public final boolean hasNext() {
return next != null;
}
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
public final void remove() {
Node<K,V> p = current;
if (p == null)
throw new IllegalStateException();
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
current = null;
K key = p.key;
removeNode(hash(key), key, null, false, false);
expectedModCount = modCount;
}
}
按照新对象的顺序。它将使用基于命令的构造函数&gt;对象---&gt;超类---&gt;最后一个本身就是
jsut like:new HashIterator()然后是新的EntryIterator()
当新的EntryIterator()时,它将使用HashIterator的构造函数 方法本身。我们可以看到它会加载HashMap的数据 我们使用HashIterator的构造方法。
nextNode()方法从这些数据中获取数据。所以我们可以使用...循环来获取HashMap Object的所有节点。
答案 1 :(得分:1)
在HashMap
内,有一个内部类
private final class EntrySet extends AbstractSet...
这是entrySet()
中HashMap
方法返回的内容。
当您调用EntrySet
类中的方法来检查其内容时,它会在HashMap
中查找信息。如果您在EntrySet
中添加或删除项目,则会影响HashMap
(反之亦然)。它本质上只是另一种查看同一容器的方式。它没有自己的Map
内容副本。
答案 2 :(得分:1)
在创建新的EntrySet()
时填充值
你在HashMap.java中看到的EntrySet不是一个新的集合,而是一个由HashMap本身支持的函数包装 (读取javadoc)。
EntrySet上的操作被委托给HashMap本身。
因此,EntrySet实际上并没有任何东西。 EntrySet不需要填充。
来自消息来源:
{{1}}
如您所见,该课程不是一个集合,而是实际地图的视图。
答案 3 :(得分:0)
entrySet()方法用于获取此映射中包含的映射的Set视图。
因此,这将返回存储在Map中的值的集合表示,但这与Map链接,因此在迭代Map期间,如果您更改任何内容,它将反映在Set中。
另一方面,该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。它不支持add或addAll操作。
查看此示例以获取有关其工作原理的详细信息。
http://www.tutorialspoint.com/java/util/hashmap_entryset.htm
答案 4 :(得分:0)
入口集不需要填充值,如果调用iterator(),它将调用 newEntryIterator(),
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
public Iterator<Map.Entry<K,V>> iterator() {
return newEntryIterator();
}
}
Iterator<Map.Entry<K,V>> newEntryIterator() {
return new EntryIterator();
}
private final class EntryIterator extends HashIterator<Map.Entry<K,V>> {
public Map.Entry<K,V> next() {
return nextEntry();
}
}
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;
}
答案 5 :(得分:-1)
你可以按照你的方式思考&lt;键,值&gt;成套。遍历地图很方便。
for (Map.Entry me: map.entrySet()) {
System.out.println("key" + me.getKey() + " value" + me.getValue());
}
而不是使用键来查找地图中的值