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

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

Equals and Comparable with Sets

javaequalscomparablecomparetotreeset

提问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 TreeSetwith a special Comparableclass which wrapped the Localethey 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 0from the compareTomethod, not by returning truefrom an equalsimplementation as one would need to do to correctly indicate a duplicate in a Set(from the definitionof a Set).

然后我开始思考......像你一样......我是通过返回消除重复0compareTo方法,而不是通过返回trueequals实现作为一个需要做的正确指示在重复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 Setinterface. (See Comparableor Comparatorfor a precise definition of consistent with equals.) This is so because the Setinterface is defined in terms of the equalsoperation, but a TreeSetinstance performs all element comparisons using its compareTo(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 the Setinterface.

请注意,如果要正确实现接口,则集合维护的排序(无论是否提供显式比较器)必须与 equals 一致Set。(请参阅ComparableComparator了解与等于一致的精确定义。)之所以如此,是因为Set接口是根据equals操作定义的,但TreeSet实例使用其compareTo(或比较)方法执行所有元素比较,因此被视为相等的两个元素被从集合的角度来看,这种方法是相等的。集合的行为是明确定义的,即使它的顺序与 equals 不一致;它只是不遵守Set接口的一般契约

Here is an example of the only (?) JDK classthat implements Comparablebut is not consistent with equals():

这是实现但与 不一致的唯一 (?) JDK 类的示例:Comparableequals()

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);

decimalsat the end have three values because 42, 42.0and 42.00are not equal as far as equals()is concerned. But if you replace HashSetwith 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在最后有三个值,因为4242.0并且42.00是不相等的,只要equals()关注。但是,如果您替换HashSetTreeSet,则结果集仅包含 1 个项目(42-恰好是添加的第一个项目),因为在使用BigDecimal.compareTo().

This shows that TreeSetis 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 Setclass - if two classes are not equal(), they are not considered duplicates.

这表明,TreeSet在某种程度上是“”使用类型的不一致时equals()。它仍然可以正常工作并且所有操作都是明确定义的——它只是不遵守Set类的约定——如果两个类不是equal(),则它们不被认为是重复的。

See also

也可以看看