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

时间:2014-04-30 03:01:01

标签: java hashmap

我想知道HashMap是否使用HashSet来存储其密钥。我猜它会这样,因为HashMap会与HashSet对应,而TreeMap会与TreeSet对应。

我查看了HashMap类的源代码,该方法返回一个由某种迭代器实现的AbstractSet。

另外......我写的时候

    HashMap map = new HashMap();

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

以上if语句永远不会运行。现在我不确定

有人可以解释HashMap如何存储其密钥吗?

4 个答案:

答案 0 :(得分:2)

  

我想知道HashMap是否使用HashSet存储其密钥。

这不会太好用,因为Set只跟踪键。它无法存储关联的值映射。

相反(使用Map来存储Set元素)是可能的,并且正在使用这种方法:

HashSet是使用HashMap(所有键的虚拟值)实现的。

HashMap#keySet返回的密钥集由私有内部类(HashMap.KeySet extends AbstractSet)实现。

您可以研究这两个类的来源,例如GrepCode:HashMapHashSet

  

有人可以解释HashMap如何存储其密钥吗?

它使用一系列桶。每个存储桶都有一个链接的条目列表。另见

答案 1 :(得分:2)

keySet返回的集仅由基础地图支持。

根据javadoc

  

返回此地图中包含的键的Set视图。该集由地图支持,因此对地图的更改将反映在集中,反之亦然。如果在对集合进行迭代时修改了映射(除了通过迭代器自己的删除操作),迭代的结果是未定义的。该集支持元素删除,它通过Iterator.remove,Set.remove,removeAll,retainAll和clear操作从地图中删除相应的映射。它不支持add或addAll操作。   块引用

HashMap将密钥存储到存储桶中。具有相同哈希码的密钥进入同一个桶。如果在桶中找到多个键,则检索键的值时,使用equals方法来查找正确的键,从而找到正确的值。

答案 2 :(得分:2)

你实际上问了两个不同的问题:

  1. HashMap是否使用HashSet存储密钥?
  2. HashMap.keySet()会返回HashSet吗?
  3. 这两个问题的答案都是否定的,并且出于同样的原因,但没有技术上的理由阻止1.或2.无效。

    HashSet实际上是HashMap的包装器; HashSet具有以下成员变量:

    private transient HashMap<E,Object> map;
    

    当对象添加到集合时,它会将PRESENT sentinel值填充为地图的值。

    现在HashMap将数据存储在包含Key,Value对的Entry个对象数组中:

    transient Entry<K,V>[] table;
    

    它的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
    }
    

    由于KeySet是一个私有的内部类,因此您应该关注它只是一个任意的Set实现。

    就像我说的那样, 没有理由这样做。您绝对可以实现内部使用Map的{​​{1}}类,然后让HashSetMap返回HashSet。然而,这将是低效且难以编码的;现有的实现比天真的.keySet() / Map实现更强大,更有效。

    从Oracle JDK 1.7.0_17获取的代码片段。您可以在Java安装目录的Set文件中查看Java版本的源代码。

答案 3 :(得分:1)

答案是:否。

HashMap.keySet()是此地图中包含的键的 VIEW

地图数据存储在Entry[]的{​​{1}}表中。