Java:如何解决缺少Equatable接口的问题?

jav*_*top 3 java collections equals comparable comparator

据我所知,事情如SortedMapSortedSet使用compareTo(而不是equals上)Comparable<?>类型检查平等(contains,containsKey).

但是,如果某些类型在概念上是等同的,但具有可比性呢?
(哈希码,内存地址,......)

我必须声明一个Comparator<?>并覆盖该方法int compareTo(T o1, To2).好的,我可以为被认为相等的实例返回0.但是,对于非实际情况,当订单不明显时我会返回什么?

使用SortedMap或SortedSet的方法是否相等,但(概念上)不可比的类型好吗?

谢谢!

编辑:
我不想存储已排序的东西,但我会使用"通常"的Map和Set,我无法"覆盖"相等行为.

编辑2:
为什么我不能覆盖equals(...):
我需要改变外来类的相等行为.我无法编辑它.

编辑3:
想想.NET:它们具有IEquatable接口,可以在不触及可比行为的情况下改变相等行为.

编辑4:
我不能只compareTo返回0表示相等,1表示不相等的实例吗?什么是大问题?我进行了一些测试,似乎SortedMap/SortedSet在一对实例上调用compareTo一次.是的,订单没有意义,但为什么它应该是我的问题呢?我不需要订单.*我只需要改变平等行为.可悲的是,大多数人都无法理解这一点.
注意:现在证明为非平等实例返回1的概念是错误的.

编辑5:
改变外国阶级的平等行为是一个坏主意吗?当然?我不这么认为:为什么我允许改变使用外国类的比较行为Comparator

编辑6:
感谢Mark Peterswaxwing将密钥类型包装在自定义类中的想法.这样,我可以覆盖equals和hashCode,从而改变相等行为.

Mar*_*ers 10

不,在相同但不可比的类型上使用SortedMap或SortedSet是一个可怕的想法.如果它们无法通过内在比较或通过比较器进行比较,则不应在SortedSet中使用它们.排序意味着有排序,这意味着你可以比较两个项目,看看哪个是"更少".

只需使用HashMap/Set.

编辑到您的编辑#2

如果你无法正确地覆盖equals,那么你的设计就会非常糟糕.您需要提供有关您要完成的内容的更多信息.

编辑到您的编辑#3

在Java中,修改equals 不会改变可比较的行为.您不需要接口来完成该任务.

编辑到您的编辑#4

不,你不能仅仅返回1个非平等元素!

SortedSets使用比较来查找集合中的元素.可比较的界面具有特定要求.你破坏的那个是,如果A.compareTo(B) > 0,那么必然B.compareTo(A) < 0.你打破那会使你无法在你的集合中找到元素.

public static void main(String[] args) throws Exception {
    SortedSet<MyClass> set = new TreeSet<MyClass>();
    MyClass one = new MyClass(1);
    set.add(one);
    set.add(new MyClass(2));
    set.add(new MyClass(3));
    System.out.println(set.contains(one));
}
private static class MyClass implements Comparable<MyClass> {
    private final int data;
    private MyClass(int data) { this.data = data; }
    public int compareTo(MyClass o) { return (data == o.data ? 0 : 1); }
}
Run Code Online (Sandbox Code Playgroud)

这段代码打印出来false,显然你的比较器打破了Set的语义.


wax*_*ing 10

考虑将您的外国课程包装在您自己的内部.

public class Foreign {
  // undesired equals() and hashCode() implementation
}


public class ForeignWrapper {
   private Foreign foreign;

   public ForeignWrapper(Foreign foreign) {
      this.foreign = foreign;
   }

   public void equals() {
       // your equals implementation, using fields from foreign
   }

   public int hashCode() {
       // your hashCode implementation, using fields from foreign
   }
Run Code Online (Sandbox Code Playgroud)

}

然后添加new ForeignWrapper(foreign)到标准的HashSet/HashMap.不适用于所有情况,但可能适用于您的情况.


rya*_*ogo 6

看起来你不想/需要对元素进行排序.

在那种情况下,也许你可以使用HashMapHashSet不是?没有必要使用SortedMap,SortedSet如果你不需要它进行排序.