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
}