Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java-为什么Map.put()覆盖而Set.add()不覆盖?_Java_Collections_Map_Set - Fatal编程技术网

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

Java-为什么Map.put()覆盖而Set.add()不覆盖?,java,collections,map,set,Java,Collections,Map,Set,我想知道Java的Map.put(key,value)方法在Set.add(value)不覆盖集合中已经存在的等价值的情况下,等效地覆盖集合中已经存在的键值的背后的原理是什么 编辑: 看起来,大多数人的观点是,集合中的对象在各个方面的计算结果都应该相等,因此set.add(Object)是否覆盖相等值的对象并不重要。如果两个对象的计算结果相等,但实际上包含不同的数据,则贴图类型集合是更合适的容器 我有点不同意这一观点。 示例:包含一组“Person”对象的集合。为了更新有关此人的某些信息,您可能

我想知道Java的
Map.put(key,value)
方法在
Set.add(value)
不覆盖集合中已经存在的等价值的情况下,等效地覆盖集合中已经存在的键值的背后的原理是什么

编辑: 看起来,大多数人的观点是,集合中的对象在各个方面的计算结果都应该相等,因此set.add(Object)是否覆盖相等值的对象并不重要。如果两个对象的计算结果相等,但实际上包含不同的数据,则贴图类型集合是更合适的容器

我有点不同意这一观点。

示例:包含一组“Person”对象的集合。为了更新有关此人的某些信息,您可能希望向集合传递一个新的、更新的person对象,以覆盖旧的、过时的person对象。在这种情况下,一个人将持有一个识别该个人的主键,集合将仅基于他们的主键识别和比较人员。此主键是个人身份的一部分,而不是地图等外部参照。

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

是的,使用
add
过度编写
Set
内容可能会改变某些东西(参考值)-但这似乎是一个非常狭窄的用例(无论如何都可以实现-总是在添加之前尝试删除:
s.remove(o);s.add(o);
),相对于大多数情况下得到的内容-对于周期来说没有任何影响

编辑:


我可以看到这种行为的一个潜在用途是,内存预算有限,创建了大量重但等效的对象,并在不同位置引用了不同的等效版本,防止重复版本的垃圾收集。然而,我以前遇到过这个问题,我认为这种行为甚至不是解决这个问题的最佳方式。

在我看来,覆盖集合中的某些内容是没有意义的,因为没有任何东西会改变


但是,当您更新地图时,键可能相同,但值可能不同。

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

  • 实现
  • 您可以创建一个可变的单例集-向该集添加内容将覆盖现有的单例值

  • 请注意,地图实际上并没有那么不同。。。它可能总是会更改值,但(至少在Sun的实现中)即使以后调用put()时使用与原始实例相同的不同实例,键也会保持不变。

    取决于您实现set的方式,它会更改。在我的例子中,我使用的是键对象。我实现了comparable和overrode.equals()和.hashcode(),因此集合只查看对象上的主键。在集合中添加元素时,我希望它用保存新信息的对象覆盖已经具有该键的任何对象。当这种情况没有发生时,我很惊讶。听起来你们真的有一个地图:
    primaryKey->object
    我最初在地图上用过。我遇到的问题是,我复制了地图和对象中的键,这为数据不一致提供了机会。有可能我可以将钥匙从对象中取出,只在地图中保留,但这可能会在其他地方造成问题。@DutrowLLC-地图中不应该有重复的钥匙,这会破坏地图的用途。@DutrowLLC,没有任何东西可以阻止您执行map.put(object.key,object)。只需确保密钥不会更改(例如,如果更改哈希代码,您的映射可能会失去对它的跟踪)。为什么要设置.add(value)覆盖?如果这是一种期望的行为,那么您实现的equals/hash是错误的,因为只有当两个对象具有所有相同的属性时,它们才应该是相等的(在这种情况下,集合中的哪一个是无关的)。但是,Put必须重写该值,否则如何为给定的键获取不同的值?下面我讨论了如何重写.equals()和.hashcode(),以便只查看对象的主键(如果它有主键)。然而,该线程上的主要论点似乎是,这种类型的数据最好在映射类型集合中表示。这不是一个你“不同意”的“观点”,而是
    java.util.Set
    的文档化行为。您当然可以创建自己的数据结构来实现您所描述的功能,但是如果您希望现有代码按照您所希望的方式运行,而不是按照其设计的方式运行,那么您将度过一段不愉快的时光。您是否真的读过javadocs for java.util.Set,特别是对于add方法,Set的javadocs清楚地表明,它旨在对Set的数学概念进行建模。它的实际功能是在实现类中指定的。编译器不强制执行javadocs注释。如果您对Java非常熟悉,您就会知道该语言没有表达能力来强制执行接口的所有合同要求。然而,您可以假设所有实现Set(或List或其他)的类都遵守契约。所有的Sun类都是这样的,如果您实现了Set而不实现,那么您的代码实际上会着火烧死您。