-5

鍵はkeySetどこから来るのですか?このクラスKeySetは の内部クラスであり、変数にHashMapアクセスできますが、参照するマップのキーのみを格納HashMapする のような直接変数はありません。Set<K>

Entry<K,V>[]テーブルしか見つかりません。しかし、それはキーと値を保存しています。メソッドは、参照を作成するために呼び出されたときに何かを行いますか
? 次のようになります。keySet()new KeySet()

for(Entry e : table) {
    keySet.put(e.getKey());
}

次に、キーセットにキーが保存され、キー値を追加または削除するとkeySet、同じキーも追加または削除されますか?

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

ソースコードには だけが表示されますnew KeySet()が、なぜ空ではないのにキーがあるのですか? 明確にするために:

Map map = new HashMap();
map.put(1, 1);  //null
map.keySet();   //[1]
map.put(2, 2);  //[1,2]
map.remove(2);  //[1]

各行でデバッグとブレークポイントを行い、各行を検査し、マップの keySet 変数を確認すると、上記の結果が表示されますよね?

keySet() が呼び出されると、put と remove は keySet に同じ効果をもたらしますよね? HashMap のメソッド put と remove を見てきました。

「put()」の場合、「table[bucketIndex] = new Entry<>(hash, key, value, e);」を呼び出した後、addEntry -> createEntry -> を呼び出した場合 keySet はキーを追加し、

for "remove()" ->removeEntryForKey -> table[i] = next; を呼び出した後。keySet のキーが削除されたので、table[] と keySet の間に何らかの関連があるに違いないと思い、この質問をしました...

4

3 に答える 3

1

keySet()によってサポートされる内部Set実装を返しますHashMap。たとえば、contains(key)その Set を呼び出すcontainsKey(key)と、 backingが呼び出されHashMapます。

オリジナルのキーを保持する独立した Set を作成しません(コードスニペットHashMapで提案したように) 。 .SetHashMapHashMapSet

Java 6 の実装は次のとおりです。

/**
 * Each of these fields are initialized to contain an instance of the
 * appropriate view the first time this view is requested.  The views are
 * stateless, so there's no reason to create more than one of each.
 */
transient volatile Set<K>        keySet = null;

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

private final class KeySet extends AbstractSet<K> {
    public Iterator<K> iterator() {
        return newKeyIterator();
    }
    public int size() {
        return size;
    }
    public boolean contains(Object o) {
        return containsKey(o);
    }
    public boolean remove(Object o) {
        return HashMap.this.removeEntryForKey(o) != null;
    }
    public void clear() {
        HashMap.this.clear();
    }
}
于 2015-08-04T08:07:28.873 に答える
0

のソース コードを参照して、java.util.HashMapこれがどのように機能するかを理解できます。

この関数は、次の JDK ソース コードが取得したようkeySet()に、実際にはインスタンスのメンバー変数を返します。HashMap

 public Set<K>  [More ...] keySet() {
     Set<K> ks = keySet;
     return (ks != null ? ks : (keySet = new KeySet()));
 }

次に、は、ローカルに定義されたクラスでkeySetある のメンバー変数です。HashMap

 private final class  [More ...] KeySet extends AbstractSet<K> {
     public Iterator<K>  [More ...] iterator() {
         return newKeyIterator();
     }

     public int  [More ...] size() {
         return size;
     }

     public boolean  [More ...] contains(Object o) {
         return containsKey(o);
     }

     public boolean  [More ...] remove(Object o) {
         return HashMap.this.removeEntryForKey(o) != null;
     }

     public void  [More ...] clear() {
         HashMap.this.clear();
     }

 }

ご覧のとおり、 に保持されている同じデータに対して別の「ビュー」を定義するだけHashMapです。何も複製されないため、keySet ビューと元のマップ ビューの間の一貫性が保証されます。

于 2015-08-04T08:11:53.433 に答える