如果我实现一个自定义比较器,除了compare
之外,重写equals
是不是一种好的做法
此外,是否有针对Comparator
的已定义合同
发布于 2012-10-04 09:23:17
比较器的契约定义为in its javadoc。特别是:
在使用能够强制使用与等于不一致的排序的比较器对排序集(或排序映射)进行排序时,应谨慎使用
。假设具有显式比较器c的有序集(或有序映射)与从集合S提取的元素(或键)一起使用。如果c对S施加的排序与相等不一致,则有序集(或有序映射)将表现得“奇怪”。特别地,排序的集合(或排序的映射)将违反集合(或映射)的一般约定,该约定以等于的形式定义。
通常,如果两个对象从equals
角度看是相等的,但从compareTo
角度看不是,那么您可以将这两个对象作为键存储在TreeMap中。这可能会导致不直观的行为。在特定情况下,也可以有目的地这样做。
例如,this answer显示了一个示例,其中和compareTo是不一致的是可取的。
发布于 2012-10-04 09:20:16
当且仅当c.compare( e1,e2)==0具有与e1.equals( e2 )相同的布尔值时,比较器c对一组元素S的排序与等于一致当且仅当S中的每个e1和e2具有相同的布尔值。
当使用能够施加与等于不一致的排序的比较器来对有序集(或有序映射)进行排序时,应谨慎操作。假设具有显式比较器c的有序集(或有序映射)与从集合S提取的元素(或键)一起使用。如果c对S施加的排序与相等不一致,则有序集(或有序映射)将表现得“奇怪”。特别地,排序的集合(或排序的映射)将违反集合(或映射)的一般约定,该约定以等于的形式定义。
所以答案是肯定的,这是一个很好的实践(至少对于你的第一个问题)。
发布于 2012-10-04 09:21:14
我认为只有当你觉得你在测试相等性时,你才需要重写equals。通常,当我编写比较器时,它们会比较对象中的属性,而我会继续对这些属性使用compareTo。
例如
public class ToCompare {
public static final Comparator<ToCompare> ID_COMPARATOR = new Comparator(){
@Override
public int compare(ToCompare o1, ToCompare o2) {
return o1.id.compareTo(o2.id);
}
}
private Integer id;
//... other fields here
}
我倾向于将这些比较器作为public static final字段存储在对象中,以便任何想要对此对象进行排序的代码都可以访问它们。如果更新了对象(添加/删除了字段),那么我可以直接看到比较器是否有问题,而不是检查所有的代码查找问题。
https://stackoverflow.com/questions/12724051
复制