2015-06-08 95 views
0

我想了解HashMap中的entrySet()函数,但我不确定它是如何工作的,以及创建新的EntrySet()时从何处填充值。entrySet()如何在HashMap内部工作?

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

如果您正在查看'HashMap'代码,请在'HashMap'中查找内部类'EntrySet'的定义。它实际上是地图内容的实时视图。 – khelwood

+0

感谢@khelwood :) 你指的是这个 - 'code' //浏览 私人转移设定> =的entrySet空; 'code' 但..Can你解释这:) – user3759177

+1

号,上面写着'私人final类EntrySet' – khelwood

回答

0

Source

里面HashMap有一个内部类

private final class EntrySet extends AbstractSet... 

这是由entrySet()方法HashMap返回。

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

+0

你能帮我找到查找部分的代码吗? – user3759177

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

-1

你能想到的,你把<键,值>为一组的方式。遍历地图很方便。

for (Map.Entry me: map.entrySet()) { 
    System.out.println("key" + me.getKey() + " value" + me.getValue()); 
} 

而不是使用键查找在地图

+0

这不回答问题。 – xTrollxDudex

0

其中创建新的entrySet当值被填充值()

的的entrySet您正在寻找在HashMap中.java不是一个新的集合,而是一个功能包装支持的HashMap本身(阅读javadoc)。

对EntrySet的操作被委托给HashMap本身。

因此,EntrySet实际上并不包含任何东西。 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(); 
    } 
} 

正如你所看到的,这个类是不是一个集合,但实际的地图,而一个视图

+0

感谢xTrollxDudex的详细解答...真正帮助:) 至于你提到 - 类的entrySet有它使用内部 https://drive.google.com/file/d/0B22APPjD496tYWhWaFlCXzBFTG8/view?usp=sharing – user3759177

+0

事实上_this_(HashMap的)对象,你是对的。虽然我不确定非静态内部类* all *是否还有与它一起存储的'this'实例:P – xTrollxDudex

0

的的entrySet是不需要填充值,如果调用迭代器(),它会调用 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; 
    } 
1

以下是的entrySet()的jdk8的源代码:

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()方法返回一个迭代器(类: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; 
    } 
} 

根据新对象的顺序。它将使用构造函数>基于该顺序:对象--->父类--->最后将自己

仅仅指刚,如:新HashIterator(),则新EntryIterator()

当新EntryIterator (),它将在其自身之前使用HashIterator的构造函数 。我们可以看到当我们使用HashIterator的构造函数方法时,它会加载HashMap的数据,当我们使用 时。

而nextNode()方法从这些数据中获取数据。所以我们可以使用for ...循环来获取HashMap Object的所有节点。