Java entrySet()如何在HashMap中内部工作?

Java entrySet()如何在HashMap中内部工作?,java,iterator,hashmap,Java,Iterator,Hashmap,我试图理解HashMap中的entrySet()函数,但我不确定它是如何工作的,以及在创建新entrySet()时从何处填充值 publicset入口集(){ 返回entrySet0(); } 私有集entrySet0(){ 集合es=入口集合; 返回es!=null?es:(entrySet=newentryset()); } 在HashMap内部有一个内部类 private final class EntrySet extends AbstractSet... 这是HashMap中的en

我试图理解HashMap中的entrySet()函数,但我不确定它是如何工作的,以及在创建新entrySet()时从何处填充值

publicset入口集(){
返回entrySet0();
}
私有集entrySet0(){
集合es=入口集合;
返回es!=null?es:(entrySet=newentryset());
}

HashMap
内部有一个内部类

private final class EntrySet extends AbstractSet...
这是
HashMap
中的
entrySet()
方法返回的内容

当您在
EntrySet
类中调用一个方法来检查其内容时,它会在
HashMap
中查找信息。如果在
入口集中添加或删除项目,则会影响
HashMap
(反之亦然)。它本质上只是另一种看待同一容器的方式。它没有自己的
映射的内容副本。

entrySet()方法用于获取此映射中包含的映射的集合视图

所以,这将返回存储在映射中的值的集合表示,但它与映射相链接,所以在映射的迭代过程中,如果您更改任何内容,它将反映在集合中

另一方面,集合支持元素移除,即通过Iterator.remove、set.remove、removeAll、retainal和clear操作从映射中移除相应的映射。它不支持添加或添加所有操作

签出此示例以获取有关其工作方式的详细信息


您可以按照将放入集合的方式进行思考。浏览地图很方便

for (Map.Entry me: map.entrySet()) {
    System.out.println("key" + me.getKey() + " value" + me.getValue());
}
而不是使用键在映射中查找值

创建新EntrySet()时填充值的位置

您在HashMap.java中看到的EntrySet不是一个新集合,而是一个由HashMap本身支持的函数包装器(请阅读javadoc)

入口集上的操作被委托给HashMap本身

因此,EntrySet实际上并不包含任何内容。不需要填充入口集

来源:

private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
        return newEntryIterator();
    }
    public boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<K,V> e = (Map.Entry<K,V>) o;
        Entry<K,V> candidate = getEntry(e.getKey());
        return candidate != null && candidate.equals(e);
    }
    public boolean remove(Object o) {
        return removeMapping(o) != null;
    }
    public int size() {
        return size;
    }
    public void clear() {
        HashMap.this.clear();
    }
}
私有最终类入口集扩展了抽象集{
公共迭代器迭代器(){
返回newEntryIterator();
}
公共布尔包含(对象o){
如果(!(映射项的实例))
返回false;
Map.Entry e=(Map.Entry)o;
条目候选项=getEntry(例如getKey());
返回候选者!=null&&candidate.equals(e);
}
公共布尔删除(对象o){
return-removeMapping(o)!=null;
}
公共整数大小(){
返回大小;
}
公共空间清除(){
HashMap.this.clear();
}
}

如您所见,该类不是集合,而是实际映射的视图。

不需要填充入口集的值,如果调用迭代器(),它将调用 newEntryInterator()

私有最终类入口集扩展了抽象集{
公共迭代器迭代器(){
返回newEntryIterator();
}
}
迭代器newEntryIterator(){
返回新的EntryIterator();
}
私有最终类EntryIterator扩展HashIterator{
publicmap.Entry next(){
返回nextEntry();
}
}
最终条目nextEntry(){
if(modCount!=预期的modCount)
抛出新的ConcurrentModificationException();
条目e=下一个;
如果(e==null)
抛出新的NoTouchElementException();
if((next=e.next)==null){
条目[]t=表格;
而(索引
以下是jdk8中entrySet()的源代码:

publicset入口集(){
设置es;
return(es=entrySet)==null?(entrySet=newentryset()):es;
}
最后一个类EntrySet扩展了AbstractSet{
公共最终整数大小(){return size;}
public final void clear(){HashMap.this.clear();}
公共最终迭代器迭代器(){
返回新的EntryIterator();//获取迭代器
}
公共最终布尔包含(对象o){
如果(!(映射项的实例))
返回false;
Map.Entry e=(Map.Entry)o;
对象键=e.getKey();
节点候选者=getNode(散列(键),键);
返回候选者!=null&&candidate.equals(e);
}
公共最终布尔删除(对象o){
if(o映射项的实例){
Map.Entry e=(Map.Entry)o;
对象键=e.getKey();
对象值=e.getValue();
return removeNode(hash(key)、key、value、true、true)!=null;
}
返回false;
}
公共最终拆分器拆分器(){
返回新的EntrySpliterator(HashMap.this,0,-1,0,0);
}

public final void forEach(consumeri如果您正在查看
HashMap
代码,请在
HashMap
中查找内部类
EntrySet
的定义。它实际上是地图内容的实时视图。谢谢@khelwood:)你指的是--
code
//查看私有瞬态集entrySet=null;
code
但我没有得到实时查看部分:(…你能解释一下吗:)不。上面写着“私有最终类入口集”的部分你可以参考这段源代码。你可以参考这段代码来了解它的内部工作原理。你可以这样做,有很多可用的资料。你能帮我找到查找部分的代码吗?这并没有回答问题。谢谢xTrollxDudex提供的详细答案…真的吗帮助:)正如您所提到的-EntrySet类有一个内部使用的(HashMap)对象,您是正确的。虽然我不确定非静态内部类是否都有
this
实例存储在一起:我发现有趣的是:EntrySet,HashMap的一个实例字段,只是
private final class EntrySet extends AbstractSet<Map.Entry<K,V>> {
    public Iterator<Map.Entry<K,V>> iterator() {
        return newEntryIterator();
    }
    public boolean contains(Object o) {
        if (!(o instanceof Map.Entry))
            return false;
        Map.Entry<K,V> e = (Map.Entry<K,V>) o;
        Entry<K,V> candidate = getEntry(e.getKey());
        return candidate != null && candidate.equals(e);
    }
    public boolean remove(Object o) {
        return removeMapping(o) != null;
    }
    public int size() {
        return size;
    }
    public void clear() {
        HashMap.this.clear();
    }
}
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;
    }
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();
        }
    }
}
final class EntryIterator extends HashIterator implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}
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;
    }
}