实现中的Java HashMap,HashSet,EntrySet关系

时间:2017-09-17 06:28:49

标签: java hashmap

java中的

HashMap有一个返回entrySet()

的函数Set<Map.Entry<K,V>>
  

该集由地图支持,因此对地图的更改将反映在中   集合,反之亦然

根据文档,我认为在HashMap创建时,正在创建HashSet,并且在HashMap上执行任何操作时会更新它。

但是,我也知道HashSet的{​​{3}}由HashMap支持,其中键是唯一的,值是相同的单身。

  1. 所以EntrySet不能在HashMap的构造函数中创建,它需要是懒惰的吗?如果没有,new HashMap()调用new HashSet()再次调用new HashMap(),直到堆爆炸。

  2. 感觉EntrySet可以使用EntrySet.Key.hashCode()EntrySet.Key.equals()进行哈希操作,这意味着HashMap的{​​{1}}实现看起来与实际的EntrySet非常相似,只是密钥的类型HashMapK不同。那我们为什么要保留两份类似的副本呢?我们可以使用Map.Entry<K,V>(一个EntrySet)吗?

1 个答案:

答案 0 :(得分:1)

  

根据文档,我认为在HashMap创建时,正在创建HashSet,并且在HashMap上执行任何操作时会更新它。

该文件并不意味着这样的事情。它只是指定集合的​​行为。

EntrySet

  • 缓存:映射将其实例保存在内存中,并在第一次请求时创建(并返回)它。从那里,任何请求都会返回它。
  • 代理(或委托人):EntrySet是一个内部类(非静态),因此它与其包含的类相关联 - HashMap。返回后,对其进行的任何操作都将委托给地图,即entrySet.remove(o) { HashMap.this.remove(o); }
  • 地图的表示(或视图)。地图可以用几种方式表示。例如,您可以将地图表示为2个(相同长度)的键和值列表。 EntrySet将其表示为单个对列表。由于地图类似于矩阵结构,因此您可以考虑将其视为行列表或列列表。
  

所以EntrySet不能在HashMap的构造函数中创建,它需要是懒惰的吗?

它可以在HashMap的构造中创建,但此时它是空的,所以没有多大意义。还不能保证它是必需的,因此没有理由创建它。

  

如果没有,new HashMap()调用new HashSet(),再次调用新的HashMap(),直到堆爆炸。

HashSet没有参与。 EntrySetHashSet都是AbstractSet的直接子类。在任何情况下,为什么set构造函数会调用map构造函数?

  

感觉EntrySet可以使用EntrySet.Key.hashCode()EntrySet.Key.equals()进行哈希操作......

EntrySet不需要自行哈希,它使用HashMap的{​​{1}}方法。

  

...这意味着hash()的实施中的HashMap看起来非常类似于实际EntrySet ...

HashMap的实现没有保留EntrySet的副本,它与它的内部类相关联。

  

...除了密钥的类型HashMapK不同。

Map.Entry<K,V>中的密钥类型与EntrySet<K, V>中的密钥类型相同。

  

那为什么我们要保留两份相似的副本?我们可以使用HashMap<K, V>(一个EntrySet)吗?

见上文,没有副本。

我引用您HashMap的{​​{3}},但您可以更轻松地在IDE中进行检查。