java 与集合相等和可比
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12761532/
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
Equals and Comparable with Sets
提问by OldCurmudgeon
I posted some code herewhich correctly solved a problem the poster had. OP wanted to remove duplicates and bring certain special items to the top of a list. I used a TreeSet
with a special Comparable
class which wrapped the Locale
they were working with to achieve what they wanted.
我在这里发布了一些代码,这些代码正确解决了海报的问题。OP 希望删除重复项并将某些特殊项目置于列表顶部。我使用了TreeSet
一个特殊的Comparable
类来包装Locale
他们正在使用的东西来实现他们想要的。
I then got to thinking ... as you do ... that I was eliminating duplicates by returning 0
from the compareTo
method, not by returning true
from an equals
implementation as one would need to do to correctly indicate a duplicate in a Set
(from the definitionof a Set
).
然后我开始思考......像你一样......我是通过返回消除重复0
从compareTo
方法,而不是通过返回true
从equals
实现作为一个需要做的正确指示在重复Set
(自定义一个的Set
)。
I have no objection to using this technique but am I using what might be considered an undocumented feature? Am I safe to assume that doing this kind of thing going forward will continue to work?
我不反对使用这种技术,但我是否使用了可能被视为未记录的功能?我可以安全地假设,今后做这种事情会继续有效吗?
回答by Tomasz Nurkiewicz
It seems like this is pretty well documented in JavaDoc of TreeSet
(bold mine):
这似乎在JavaDoc ofTreeSet
(bold mine) 中有很好的记录:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equalsif it is to correctly implement the
Set
interface. (SeeComparable
orComparator
for a precise definition of consistent with equals.) This is so because theSet
interface is defined in terms of theequals
operation, but aTreeSet
instance performs all element comparisons using itscompareTo
(or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of theSet
interface.
请注意,如果要正确实现接口,则集合维护的排序(无论是否提供显式比较器)必须与 equals 一致
Set
。(请参阅Comparable
或Comparator
了解与等于一致的精确定义。)之所以如此,是因为Set
接口是根据equals
操作定义的,但TreeSet
实例使用其compareTo
(或比较)方法执行所有元素比较,因此被视为相等的两个元素被从集合的角度来看,这种方法是相等的。集合的行为是明确定义的,即使它的顺序与 equals 不一致;它只是不遵守Set
接口的一般契约。
Here is an example of the only (?) JDK classthat implements Comparable
but is not consistent with equals()
:
这是实现但与 不一致的唯一 (?) JDK 类的示例:Comparable
equals()
Set<BigDecimal> decimals = new HashSet<BigDecimal>();
decimals.add(new BigDecimal("42"));
decimals.add(new BigDecimal("42.0"));
decimals.add(new BigDecimal("42.00"));
System.out.println(decimals);
decimals
at the end have three values because 42
, 42.0
and 42.00
are not equal as far as equals()
is concerned. But if you replace HashSet
with TreeSet
, the resulting set contains only 1 item (42
- that happened to be the first one added) as all of them are considered equal when compared using BigDecimal.compareTo()
.
decimals
在最后有三个值,因为42
,42.0
并且42.00
是不相等的,只要equals()
关注。但是,如果您替换HashSet
为TreeSet
,则结果集仅包含 1 个项目(42
-恰好是添加的第一个项目),因为在使用BigDecimal.compareTo()
.
This shows that TreeSet
is in a way "broken" when using types not consistent with equals()
. It still works properly and all operations are well-defined - it just doesn't obey the contract of Set
class - if two classes are not equal()
, they are not considered duplicates.
这表明,TreeSet
在某种程度上是“破”使用类型的不一致时equals()
。它仍然可以正常工作并且所有操作都是明确定义的——它只是不遵守Set
类的约定——如果两个类不是equal()
,则它们不被认为是重复的。