它在Comparator接口的合同中说,它必须与equals一致。
如果equalsTo = true,这是否意味着Comparator = 0,或者如果并且仅当 equalsTo = true时它是否意味着Comparator = 0?
我似乎记得它是第二个,但我遇到了许多按非唯一子属性排序的比较器。
例如,我可能有对象具有子属性日期,我想按提交日期对对象列表进行排序。但是,您可以使用相同日期的多个对象?这有什么后果?当然这个问题已经有了最佳实践解决方案吗?如何在没有违反比较合同的情况下对属性进行排序,并且不保证是唯一的?这种违规行为会带来什么后果?它们可以管理吗?
答案 0 :(得分:6)
比较器必须与equals保持一致,这一点都不是真的。
文档只是警告这种情况:
当使用能够强加与equals不一致的排序的比较器来排序有序集(或有序映射)时,应该小心(http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html)
如果你有一个基于日期的订购,另一个基于日期+时间的订购,你应该简单地实现多个比较器。
也许你比较Comparator和Comparable?对于Comparable,文档强烈反对这种情况:
强烈建议(尽管不要求)自然排序与equals一致。 (http://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html)
如果你意识到一个对象只能有一个Comparable的实现,但是Comparator的多个实现,那么这种差异是有意义的。比较器的整个想法是有多种方法来比较同一个类。
答案 1 :(得分:2)
编辑 您可以拥有多个Comparators
,而 popovitsj 表示他们不一定要与之保持一致equals
(虽然我假设大部分时间都有Comparator.compare(obj1, obj2) == 0
< => obj1.equals(obj2) == true
)
如果您希望在按非唯一字段排序时获得特定的排序结果,则需要自定义Comparator
以解决这些问题,
例如,在实施compare()
时,您会遇到obj1.date == obj2.date
,那么您应该将其他重要字段(姓名,年龄等)与obj1
与obj2
进行比较并返回相应的值。
希望有所帮助。
答案 2 :(得分:0)
正如您所怀疑的,为了使compareTo()
与equals()
保持一致,compareTo()
必须始终在0
时返回equals()
}返回true
。同样,如果equals
返回false
,则compareTo
不得返回0
。
然而,正如popovitsj在他的回答中指出的那样,与equals()
的一致性不是一个要求。因此,上述内容仅适用于您尝试使两种方法保持一致的情况。
答案 3 :(得分:0)
它在Comparator接口的合同中说,它必须与equals一致。
这不完全正确;请参阅@popovitjs的回答。
如果equalsTo = true,这是否意味着Comparator = 0,或者当且仅当equalsTo = true时,它是否意味着Comparator = 0?
这意味着后者。但是,它实际上并不是Comparator
个对象的硬性要求。
我似乎记得它是第二个,但我遇到了许多按非唯一子属性排序的比较器。
这是合理的,因为它实际上并不是一项艰难的要求。事实上,如果您要将其与Comparator
一起使用,那么与equals(Object)
不一致的Arrays.sort(...)
就可以了。问题仅出现在TreeSet
和TreeMap
。
例如,假设您有Comparator<E> C
表示e1
且e2
不相等,但e1.equals(e2)
返回true
。现在假设您使用比较器创建TreeSet<E>
实例,然后将e1
和e2
添加到该集合中。集合的树基于比较器进行组织,因此e1
和e2
将插入搜索树中的不同位置,并且都将成为集合的元素。但违反 Set
的主要不变量...基于equals
方法。
正如TreeSet
的javadoc所说:
“请注意,如果要正确实现Set接口,则由一个集合维护的排序(无论是否提供显式比较器)必须与equals一致。(请参阅Comparable或Comparator以获得精确定义与equals一致。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此这个方法认为相同的两个元素是,从集合的角度看,相等。集合的行为即使其排序与equals不一致也是明确定义的;它只是不遵守Set接口的一般契约。“
这回答了你问题的最后部分。
此类违规会产生什么后果?
如果在TreeSet或TreeMap中使用不一致的Comparator,则该集合将不遵守Set
或Map
合同。
答案 4 :(得分:-1)
a 和 b 可能不相等。但是,如果在比较 a 和 b 时比较器为零,则在比较 b 和 a 时应该为零。
在this answer中说:
通常,如果2个对象从等于透视图相等但不是从compareTo透视图中等于,则可以将这两个对象作为键存储在TreeMap中。这可能导致不直观的行为。它也可以在特定情况下有目的地完成。
但这是针对特定情况通常没有什么可以阻止你在等于和compareTo行为不一致时出现不一致的行为。
一个例子,今天早上有人问:Move specific items to the end of a list
大多数答案的比较器对于不相等的元素返回0。