2015-06-08 99 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的所有節點。