II无法理解实现Comparable接口时,类的自然排序应该如何“与equals保持一致”。我在程序中发现了一个缺陷,因此我在界面Comparable的文档中检查了它。我的问题是,尽管基于equals方法将两个对象视为不同的,但TreeMap结构将它们视为相等,因此不接受第二个插入。示例代码是:使用Comparable比较对象并在TreeMap中对它们进行排序
public class Car implements Comparable<Car> {
int weight;
String name;
public Car(int w, String n) {
weight=w;
name=n;
}
public boolean equals(Object o){
if(o instanceof Car){
Car d = (Car)o;
return ((d.name.equals(name)) && (d.weight==weight));
}
return false;
}
public int hashCode(){
return weight/2 + 17;
}
public String toString(){
return "I am " +name+ " !!!";
}
public int compareTo(Car d){
if(this.weight>d.weight)
return 1;
else if(this.weight<d.weight)
return -1;
else
return 0;
}
/*public int compareTo(Car d){
return this.name.compareTo(d.name);
}*/
}
public static void main(String[] args) {
Car d1 = new Car(100, "a");
Car d2 = new Car(110, "b");
Car d3 = new Car(110, "c");
Car d4 = new Car(100, "a");
Map<Car, Integer> m = new HashMap<Car, Integer>();
m.put(d1, 1);
m.put(d2, 2);
m.put(d3, 3);
m.put(d4, 16);
for(Map.Entry<Car, Integer> me : m.entrySet())
System.out.println(me.getKey().toString() + " " +me.getValue());
TreeMap<Car, Integer> tm = new TreeMap<Car, Integer>(m);
System.out.println("After Sorting: ");
for(Map.Entry<Car, Integer> me : tm.entrySet())
System.out.println(me.getKey().toString() + " " +me.getValue());
}
的输出是:
I am a !!! 16
I am c !!! 3
I am b !!! 2
After Sorting:
I am a !!! 16
I am c !!! 2
也就是说,对象C所取代(有点)对象b。 如果我评论原来的equals方法,并取消对第二equals方法,它根据名称的对象进行比较,输出的预期:
I am a !!! 16
I am c !!! 3
I am b !!! 2
After Sorting:
I am a !!! 16
I am b !!! 2
I am c !!! 3
它为什么会来到我身边这样,我应该如何改变,以在TreeMap中插入和排序具有相同值的某些属性的不同对象?
我想,既然Map(HasMap)接受给定的元素,因为它们是不同的名称,所以也应该对它们进行处理。考虑到equals方法,HashMap区分了两个对象。我认为TreeMap只使用compareTo进行排序,而不是接受或拒绝插入元素。 – arjacsoh
@arjacsoh:您是否阅读过“TreeMap”的文档?它进行了一些细节。 –
根据TreeMap doc:“但是一个映射使用它的compareTo(或compare)方法执行所有的关键比较,所以从排序映射的角度看,这个方法认为相等的两个关键字是相等的。”所以它将compareTo用于“所有关键比较”,而不仅仅用于排序。 – arcy