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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2978087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 15:10:03  来源:igfitidea点击:

Java - Why does Map.put() overwrite while Set.add() does not?

javacollectionsmapset

提问by Chris Dutrow

I am wondering what the rationale is behind having Java's Map.put(key, value)method overwrite equivalently key'd values that are already in the collection, while Set.add(value)does not overwrite a pre-existing equivalent value that is already in the collection?

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

Edit:

编辑:

It looks like majority viewpoint is that objects in a set that evaluate to equality should be equal in every respect, thus it shouldn't matter if Set.add(Object) overwrites equivalently valued objects or not. If two objects evaluate to equality, but do in fact hold different data, then a Map-type collection is a more appropriate container.

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

I somewhat disagree with this veiwpoint.
Example: A set holding a group of "Person" objects. In order to update some information about that person, you might want to pass the set a new, updated, person object to overwrite the old, outdated person object. In this case, a Person would hold a primary key that identifies that individual and the set would identify and compare people based only on their primary keys. This primary key is part of the person's identity as opposed to an external reference such as a Map would imply.

我有点不同意这个观点。
示例:包含一组“人”对象的集合。为了更新有关该人的一些信息,您可能希望向 set 传递一个新的、更新的 person 对象以覆盖旧的、过时的 person 对象。在这种情况下,一个人将持有一个主键来标识该个人,而该集合将仅根据他们的主键来识别和比较人。这个主键是个人身份的一部分,而不是像 Map 这样的外部引用。

采纳答案by Carl

The Mapbehavior allows changing the values associated with equivalent keys. That is a pretty common use case: a : bbecomes a : c.

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

Yes, over-writing Setcontents with addcould change something (reference value) - but that seems like a pretty narrow use case (which can be accomplished anyways - always try to remove before adding: s.remove(o); s.add(o);) relative to what one would be getting in most cases - nothing for cycles.

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

edit:

编辑:

the one potential use I could see for that behavior, is having a constrained memory budget, lots of heavy-but-equivalent objects being created, and having references to different equal versions in various places, preventing garbage collection of the duplicate ones. Having run into that problem before, however, I don't think this behavior is even the best way to solve it.

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

回答by Alexandru Luchian

In my opinion, there is no point in overwriting something in Set, since nothing will change.

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

However when you update a map, the key might be the same, but the value might be different.

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

回答by emory

I disagree with the premise of your question. Both Map and Set are abstract interfaces. Whether they overwrite or not is an implementation detail.

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

  1. an implementation of Map that does not overwrite.
  2. You could create a mutable singleton set - adding stuff to the set overwrites the existing singleton value.
  1. 不会覆盖Map实现。
  2. 您可以创建一个可变的单例集 - 向该集中添加内容会覆盖现有的单例值。

回答by Jules

Note that Map isn't actually so different... it may always change the value, but (at least in Sun's implementations) the key will remain the same even if later calls to put() use a different instance that compares as equal to the original.

请注意 Map 实际上并没有那么不同......它可能总是改变值,但是(至少在 Sun 的实现中)即使稍后对 put() 的调用使用不同的实例,该实例也将保持不变原本的。