Java:如何解决缺少可均衡接口的问题?

Java:如何解决缺少可均衡接口的问题?,java,collections,equals,comparator,comparable,Java,Collections,Equals,Comparator,Comparable,据我所知,诸如SortedMap或SortedSet,使用compareTo(而不是equals)对可比的类型进行相等性检查(包含,包含) 但是,如果某些类型在概念上是相等的,但不具有可比性呢? (散列码、内存地址等) 我必须声明一个比较器并重写方法int compareTo(to1,To2)。好的,对于被认为相等的实例,我可以返回0。但是,对于非定量的例子,当订单不明显时,我应该返回什么 在上使用SortedMap或SortedSet的方法是否可以但(根据概念)不可比较类型 谢谢大家! 编辑:

据我所知,诸如
SortedMap
SortedSet
,使用
compareTo
(而不是
equals
)对
可比的
类型进行相等性检查(
包含
包含

但是,如果某些类型在概念上是相等的,但不具有可比性呢?
(散列码、内存地址等)

我必须声明一个
比较器
并重写方法
int compareTo(to1,To2)
。好的,对于被认为相等的实例,我可以返回0。但是,对于非定量的例子,当订单不明显时,我应该返回什么

上使用SortedMap或SortedSet的方法是否可以但(根据概念)不可比较类型

谢谢大家!

编辑:
我不想存储已排序的内容,但如果使用“常规”映射和集合,我无法“覆盖”相等行为

编辑2:
为什么我不能重写
等于(…)

我需要改变一个外国类的平等行为。我无法编辑它。

编辑3:
试想一下.NET:它们有一个IEquatable接口,可以在不涉及可比较行为的情况下更改相等行为

编辑4:
我不能只进行
compareTo
对相等实例返回0,对不相等实例返回1吗?有什么大问题?我做了一些测试,似乎SortedMap/SortedSet在一对实例上调用了compareTo。是的,这个命令毫无意义,但为什么这是我的问题呢?我不需要订单*我只需要改变我的行为。不幸的是,大多数人就是不明白这一点。
注意:对于不相等的实例返回1的概念现在被证明是错误的

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

编辑6:

感谢
markpeters
waxwing
在自定义类中包装键类型的思想。这样,I可以重写equals和hashCode,从而改变相等行为。

如果对象不可比较,则无法对其进行排序;如果两个对象不具有可比性,您如何知道它们中的哪一个应该排在第一位?因此,无法在
SortedMap
SortedSet
中放置不可比较的对象。(为什么要这样做?请使用不同类型的
映射

Java中的
equals()
方法是在类
Object
中定义的,由于所有类都扩展了
Object
,所以所有对象都有一个
equals()
方法。如果您想知道两个对象是否相等,必须注意在类中正确重写和实现
equals()


如果要将对象放入基于哈希的集合(例如
HashMap
HashSet
),还必须覆盖
hashCode()
,并且必须确保
hashCode()
equals()
以正确的方式实现(有关如何执行此操作的详细信息,请参阅类
Object
中这些方法的文档).

不,在可对等但不可比较的类型上使用SortedMap或SortedSet是一个可怕的想法。如果它们在本质上或通过比较器不可比较,则不应在SortedSet中使用。Sorted表示存在排序,这意味着可以比较两个项目,以确定哪一个“更少”

只需使用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); }
}
publicstaticvoidmain(字符串[]args)引发异常{
SortedSet集合=新树集合();
MyClass 1=新的MyClass(1);
设置。添加(一个);
添加(新MyClass(2));
添加(新MyClass(3));
System.out.println(set.contains(一个));
}
私有静态类MyClass实现了可比较的{
私人最终int数据;
私有MyClass(int data){this.data=data;}
public int compareTo(MyClass o){return(data==o.data?0:1);}
}

此代码打印出
false
,因此很明显,您的比较器破坏了集合的语义。

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

在这种情况下,也许您可以使用
HashMap
HashSet
来代替?如果您不需要对其进行排序,那么使用
SortedMap
SortedSet
是没有意义的

我不想存储已排序的内容,但如果使用“常规”映射和集合,我无法“覆盖”相等行为

如果不想存储已排序的元素,那么为什么要使用已排序的集合

为了维护已排序的集合,插入操作(通常)具有O(logn)复杂性,以便将元素放置在正确的位置。如果不需要排序,则这是浪费,因为您可能使用基于哈希的集合(HashMap,HashSet),这将为您提供O(1)inserti
SortedSet<MyObject> s = new TreeSet<MyObject>(new Comparator<MyObject>() {
    @Override
    public int compare(T o1, T o2) {
        // your very specific, fancy dancy code here
    }
});
SortedSet<String> set = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
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
   }
interface Equality<T>//Defines the equality behavior
{
   int hashCode(T t);//Required, always make sure equals = true => same hashCode
   boolean areEqual(T t,Object t2);
}
class EqualWrapper<T>//Wraps object and equality for the HashMap/Set
{
   T object;
   Equality<T> equal;
   int hashCode(){return equal.hashCode(object);}
   boolean equals(Object o){return equal.areEqual(object,o);}

}
class MySet<T>extends AbstractSet<T>
{
   private HashSet<EqualWrapper<T> > internalSet = new HashSet<T>();
   private Equality<T> equal;
   public MySet(Equality<T> et){equal = et;}
   // TODO implement abstract functions to wrapp 
   // objects and forward them to 
   // internalSet  
}