簡體   English   中英

HashMap.keySet()如何返回鍵的視圖?

[英]How can HashMap.keySet() return a view of keys?

這是java.util.HasMap類中的keySet()函數:

public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

在評論中,它說這個功能

返回此映射中包含的鍵的{@link Set}視圖。 該集由地圖支持,因此對地圖的更改將反映在集中,反之亦然。

因此,我期望KeySet類型的對象,此函數返回的對象將包含對“視圖鍵”的引用。 但是,當我查看代碼時,KeySet類根本不包含任何字段及其所有超類。

final class KeySet extends AbstractSet<K> {
    public final int size()                 { return size; }
    public final void clear()               { HashMap.this.clear(); }
    public final Iterator<K> iterator()     { return new KeyIterator(); }
    public final boolean contains(Object o) { return containsKey(o); }
    public final boolean remove(Object key) {
        return removeNode(hash(key), key, null, false, true) != null;
    }
    public final Spliterator<K> spliterator() {
        return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
    }
    public final void forEach(Consumer<? super K> 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.key);
            }
            if (modCount != mc)
                throw new ConcurrentModificationException();
        }
    }
}

有人可以解釋一下

  1. “鑰匙的視圖”是什么意思? 什么樣的數據是“觀點”?
  2. HashMap.keySet()如何通過使用KeySet對象返回鍵的視圖,該對象根本不包含對任何內容的任何引用?

為了更清楚:

這是打印出鍵集值的代碼示例。 雖然KeySet對象保存對包含的地圖數據的引用,但是如何准確地輸出關鍵數據而不是地圖的其他數據(不是值數據或其他任何數據)。 什么是告訴這個KeySet對象只保存MapKeys? 我在代碼中看不到這樣的指令。

package com.tutorialspoint;
import java.util.*;

public class HashMapDemo {
   public static void main(String args[]) {

     // create hash map
     HashMap newmap = new HashMap();

     // populate hash map
     newmap.put(1, "tutorials");
     newmap.put(2, "point");
     newmap.put(3, "is best");

     // get keyset value from map
     Set keyset = newmap.keySet();

     // check key set values
     System.out.println("Key set values are: " + keyset);
   }    
}

輸出:

鍵集值為:[1,2,3]

  1. 視圖 ”是一種對象,其數據由不同的對象支持,但以不同的方式提供。 在這種情況下,它提供Map的鍵的“視圖”作為Set 這對用戶和性能都有很多好處。

    值得注意的是,由於它與支持類共享其數據,因此內存開銷非常小 - 它不需要將所有鍵復制到一個全新的Set 此外,用戶無需擔心視圖與支持結構不同步 - 添加和刪除將立即通過視圖顯示。

  2. 因為KeySet是一個內部類,所以它可以訪問其包含類( HashMap )的實例的字段。 請注意代碼段中的HashMap.this表示法。

    • size()return size; 是對HashMapsize字段的引用
    • clear()HashMap.this.clear(); 調用HashMapclear()方法(它需要使用HashMap.this來引用map的clear()方法而不是它自己的方法)
    • contains()代表HashMapcontainsKey()方法-這並不需要HashMap.this因為KeySet沒有碰撞containsKey()方法
    • remove()類似地委托給HashMapremoveNode()

    如果它被聲明為final static class KeySet那么它將是一個靜態嵌套類,它不依賴於包含類的實例(它只是組織相關類的一種方式)。 在這種情況下, KeySet需要一個顯式的HashMap字段,並且需要將有問題的地圖傳遞給構造函數。 內部類使這隱含(這是簡潔的,但有時令人困惑)。

  3. 什么是告訴這個KeySet對象只保存MapKeys?

    要明確的是,沒有這樣的指示。 KeySet實例可以傳遞地訪問支持映射的所有字段和方法。 但是您的示例( System.out.println("Key set values are: " + keyset); keyset.toString() System.out.println("Key set values are: " + keyset); )隱式調用keyset.toString() ,這是(有意)未實現以返回映射的值。 因為KeySet擴展了AbstractSet (后者又擴展了AbstractCollection ),所以.toString()依賴於KeySetiterator()實現,該實現提供了映射鍵的迭代器,而不是其值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM