Java - 为什么Map.put()会覆盖而Set.add()不会覆盖?

时间:2010-06-04 22:01:49

标签: java collections map set

我想知道让Java的Map.put(key, value)方法覆盖已经在集合中的等价键值的原因是什么,而Set.add(value)不会覆盖已经存在的等价值在集合中?

编辑:

看起来多数人的观点是,评估为相等的集合中的对象在每个方面都应该相等,因此如果Set.add(Object)覆盖等价的对象则无关紧要。如果两个对象评估为相等,但实际上确实包含不同的数据,那么Map类型集合是更合适的容器。

我有点不同意这个观点 示例:包含一组“Person”对象的集合。为了更新有关该人员的某些信息,您可能希望传递该集合一个新的,更新的人员对象来覆盖旧的,过时的人员对象。在这种情况下,Person将持有一个主键,用于标识该个人,并且该集合将仅基于其主键来识别和比较人员。这个主键是人的身份的一部分,而不是外部参考,如地图意味着。

4 个答案:

答案 0 :(得分:9)

Map行为允许更改与等效键关联的值。这是一个非常常见的用例:a : b变为a : c

是的,用Set覆盖add内容可能会改变某些内容(参考值) - 但这似乎是一个非常狭窄的用例(无论如何都可以完成 - 总是在添加之前尝试删除:s.remove(o); s.add(o);)相对于大多数情况下的情况 - 没有任何循环。

编辑:

我可以看到这种行为的一个潜在用途,就是有一个受限的内存预算,创建了大量重等但是等价的对象,并且在不同的地方引用了不同的相同版本,防止了重复版本的垃圾收集。然而,在遇到这个问题之前,我认为这种行为甚至不是解决它的最好方法。

答案 1 :(得分:5)

在我看来,在Set中覆盖一些东西是没有意义的,因为什么都不会改变。

但是,更新地图时,密钥可能相同,但值可能不同。

答案 2 :(得分:1)

请注意,Map实际上并没有那么不同......它可能总是更改值,但是(至少在Sun的实现中)即使稍后调用put()使用不同的实例进行比较,密钥也将保持不变等于原来的。

答案 3 :(得分:0)

我不同意你的问题的前提。 Map和Set都是抽象接口。它们是否覆盖是一个实现细节。

  1. Map that does not overwrite的实现。
  2. 你可以创建一个可变的单例集 - 向集合添加东西会覆盖现有的单例值。