简体   繁体   English

HashMap是否使用HashSet来存储其密钥?

[英]Does a HashMap use a HashSet to store its keys?

I'm wondering if a HashMap uses a HashSet to store its keys. 我想知道HashMap是否使用HashSet来存储其密钥。 I would guess it does, because a HashMap would correspond with a HashSet, while a TreeMap would correspond with a TreeSet. 我猜想是的,因为HashMap将与HashSet对应,而TreeMap将与TreeSet对应。

I looked at the source code for the HashMap class, and the method returns an AbstractSet that's implemented by some kind of Iterator. 我查看了HashMap类的源代码,该方法返回了由某种Iterator实现的AbstractSet。

Additionally...when I write 另外...当我写

    HashMap map = new HashMap();

    if(map.keySet() instanceof HashSet){
        System.out.println("true");
    }

The above if statement never runs. 上面的if语句永远不会运行。 Now I'm unsure 现在我不确定

Could someone explain how the HashMap stores its keys? 有人可以解释HashMap如何存储其密钥吗?

I'm wondering if a HashMap uses a HashSet to store its keys. 我想知道HashMap是否使用HashSet来存储其密钥。

That would not work too well, because a Set only keeps track of the keys. 这不会太好用,因为Set只跟踪键。 It has no way to store the associated value mapping. 它无法存储关联的值映射。

The opposite (using a Map to store Set elements) is possible, though, and this approach is being used: 但是,可能相反(使用Map存储Set元素),并且正在使用这种方法:

HashSet is implemented by using a HashMap (with a dummy value for all keys). HashSet是通过使用HashMap (对于所有键都具有虚拟值)实现的。

The set of keys returned by HashMap#keySet is implemented by a private inner class ( HashMap.KeySet extends AbstractSet ). HashMap#keySet返回的键集由私有内部类实现( HashMap.KeySet extends AbstractSet )。

You can study the source for both class, for example on GrepCode: HashMap and HashSet . 您可以研究两个类的源代码,例如在GrepCode上: HashMapHashSet

Could someone explain how the HashMap stores its keys? 有人可以解释HashMap如何存储其密钥吗?

It uses an array of buckets. 它使用一组存储桶。 Each bucket has a linked list of entries. 每个存储桶都有一个链接的条目列表。 See also 也可以看看

The set that is returned by the keySet is backed by the underlying map only. keySet返回的集合仅由基础映射支持。

As per javadoc 根据javadoc

Returns a Set view of the keys contained in this map. 返回此映射中包含的键的Set视图。 The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. 该集合由地图支持,因此对地图的更改会反映在集合中,反之亦然。 If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. 如果地图被同时修改了设置的迭代过程中(除了通过迭代器自己的remove操作),则迭代的结果是不确定的。 The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. 该组支持元件移除,即从地图相应的映射,通过Iterator.remove,Set.remove,的removeAll,retainAll和清除操作。 It does not support the add or addAll operations. 它不支持add或addAll操作。 Blockquote 块引用

HashMap stores keys into buckets. HashMap的存储键进入桶中。 Keys that have same hash code goes into the same bucket. 具有相同哈希码的密钥将进入同一存储桶。 When retrieving value for an key if more than one key is found in the bucket than equals method is used to find the right key and hence the right value. 当如果超过一个关键是在比equals方法桶检索发现一个键值来找到合适的关键,因此正确的价值。

You're actually asking two different questions: 您实际上是在问两个不同的问题:

  1. Does a HashMap use a HashSet to store its keys? HashMap是否使用HashSet来存储其密钥?
  2. Does HashMap.keySet() return a HashSet ? HashMap.keySet()返回HashSet吗?

The answer to both questions is no, and for the same reason, but there's no technical reason preventing either 1. or 2. from being true. 这两个问题的答案都是“否”,并且出于相同的原因,但是没有技术上的理由阻止1.或2.成立。

A HashSet is actually a wrapper around a HashMap ; HashSet实际上是HashMap的包装器; HashSet has the following member variable: HashSet具有以下成员变量:

private transient HashMap<E,Object> map;

It populates a PRESENT sentinel value as the value of the map when an object is added to the set. 当将对象添加到集合中时,它将填充PRESENT前哨值作为地图的值。

Now a HashMap stores it's data in an array of Entry objects holding the Key, Value pairs: 现在, HashMap将其数据存储在包含键,值对的Entry对象数组中:

transient Entry<K,V>[] table;

And it's keySet() method returns an instance of the inner class KeySet : 它的keySet()方法返回内部类KeySet的实例:

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

private final class KeySet extends AbstractSet<K> {
  // minimal Set implementation to access the keys of the map
}

Since KeySet is a private inner class, as far as you should be concerned it is simply an arbitrary Set implementation. 由于KeySet是一个私有内部类,因此就您所需要的而言,它只是一个任意的Set实现。

Like I said, there's no reason this has to be the case. 就像我说的,我们没有理由这样具有如此。 You could absolutely implement a Map class that used a HashSet internally, and then have your Map return a HashSet from .keySet() . 您可以绝对实现内部使用HashSetMap类,然后让Map.keySet()返回HashSet However this would be inefficient and difficult to code; 然而,这将是低效率的并且难以编码。 the existing implementation is both more robust and more efficient than naive Map / Set implementations. 现有的实现比朴素的Map / Set实现更加健壮和高效。

Code snippets taken from Oracle JDK 1.7.0_17. 摘自Oracle JDK 1.7.0_17的代码片段。 You can view the source of your version of Java inside the src.zip file in your Java install directory. 您可以在Java安装目录中的src.zip文件中查看Java版本的源。

Answer is: NO. 答案是:否。

HashMap.keySet() is a VIEW of the keys contained in this map. HashMap.keySet()是此映射中包含的键的VIEW

The data of the map is stored in Entry[] table of HashMap . 映射数据存储在HashMap Entry[]表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM