为什么HashSet在内部实现为HashMap

时间:2011-01-14 15:12:05

标签: java

  

可能重复:
  Why does HashSet implementation in Sun Java use HashMap as its backing?

我知道hashset和hashmap是什么 - 非常精通它们。 有一件事让我很困惑。

示例:

Set <String> testing= new HashSet <String>();

现在,如果您在上述语句之后立即使用eclipse进行调试,则在调试器变量选项卡下,您会注意到内部的“测试”集合实现为哈希映射。

为什么它需要一个hashmap,因为sets collection

中没有关键的值对

7 个答案:

答案 0 :(得分:2)

这是一个实现细节。 HashMap实际上用作HashSet的后备存储。 From the docs

  

此类实现Set接口,由哈希表(实际上是HashMap实例)支持。它不能保证集合的迭代顺序;特别是,它不保证订单会随着时间的推移保持不变。该类允许null元素。

(强调我的)

答案 1 :(得分:1)

答案恰好在API文档中

“此类实现了Set接口,由哈希表(实际上是HashMap实例)支持。它不保证集合的迭代顺序;特别是,它不保证顺序将保持不变这个类允许null元素。

该类为基本操作(添加,删除,包含和大小)提供恒定的时间性能,假设散列函数在桶之间正确地分散元素。迭代此集合需要的时间与HashSet实例的大小(元素数量)加上后备HashMap实例的“容量”(桶数)之和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低)非常重要。“

所以你甚至不需要调试器就知道这一点。

回答你的问题:这是一个实施细节。它不需要 来使用HashMap,但它可能只是很好的代码重用。如果你考虑一下,在这种情况下,唯一的区别是一个Set与Map有不同的语义。也就是说,map有get(key)方法,而sets没有。集不允许重复,映射允许重复值,但它们必须位于不同的键下。

使用HashMap作为HashSet的支持可能非常容易,因为你要做的就是在你放入Set的值中使用hashCode(在所有对象上定义)以确定是否欺骗,也就是说,它可能正在做类似

的事情
backingHashMap.put(toInsert.hashCode(), toInsert);

将项目插入到Set中。

答案 2 :(得分:0)

在大多数情况下,Set实现为Map的keySet()的包装器。这避免了重复的实现。如果您查看源代码,您将看到它是如何做到的。

你可能会发现方法Collections.newSetFromMap(),它可以用来包装ConcurrentHashMap。

答案 3 :(得分:0)

该类的Javadoc的第一句话说它由HashMap支持:

  

此类实现Set接口,由哈希表(实际上是HashMap实例)支持。

如果您查看HashSet的源代码,您会看到它在地图中存储的内容是关键是您正在使用的条目,并且该值仅仅是标记Object(已命名PRESENT)。

为什么它由HashMap支持?因为这是在(概念)哈希表中存储一组项的最简单方法,并且HashSet不需要重新发明哈希表数据结构的实现。

答案 4 :(得分:0)

标准Java类库使用HashSet实现HashMap只是为了方便,它们只需要实现一个数据结构,然后HashSet将其数据存储在一个数据结构中。 HashMap以实际设置对象为键,虚拟值(通常为Boolean.TRUE)为值。

答案 5 :(得分:0)

HashMap已经具备了HashSet所需的所有功能。复制相同的算法是没有意义的。

答案 6 :(得分:0)

它允许您轻松快速地确定对象是否已在集合中。