当实现可比接口时,我不明白类的自然顺序应该如何“与相等的一致”。我在我的程序中检测到一个缺陷,因此我在接口可比的文档中检查了它。我的问题是,虽然两个Object在equals方法的基础上被认为是不同的,但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
为什么会出现这种情况?为了在树形图中插入和排序具有相同属性的不同对象,我应该修改什么?
也就是说,对象c已经(在某种程度上)替换了对象b。
是的,可以。它们的权重相等,因此TreeMap
认为它们相等。映射从不包含两个“相等”键(如何查找值?),因此,一个替代另一个。
如果您不希望将它们视为相等,则需要使用比较方法来区分它们(例如,使用
名称
作为次要排序顺序)。
TreeMap
的文档说明,如果compareTo
方法与equals
方法不一致(事实并非如此),则无法获得正常的Map
行为:
请注意,与任何排序映射一样,树映射维护的顺序,以及是否提供了显式比较器,如果此排序映射要正确实现映射接口,则必须与equals一致。(参见可比或比较器,了解与等于一致的精确定义。)这是因为映射接口是根据equals操作定义的,但排序映射使用其compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,此方法认为相等的两个键是相等的。排序映射的行为定义良好,即使其顺序与equals不一致;只是没有遵守地图界面的总合同。
您的compareTo()
方法与equals()
不一致:
当且仅当c.compare(e1,e2)==0
具有与e1相同的布尔值。对于每个
。e1
和e2
[…],等于(e2)
试试这个:
public int compareTo(Car d){
if(this.weight>d.weight)
return 1;
else if(this.weight<d.weight)
return -1;
else
return this.name.compareTo(d.name);
}
在最初的实现中,当两个对象具有相同的权重
但不同的
名称
,而它们在
equals()方面不同时,就比较器而言,它们被认为是相等的。
当两个权重相等时,compareTo()
需要检查名称:
public int compareTo(Car d){
if(this.weight>d.weight)
return 1;
else if(this.weight<d.weight)
return -1;
return this.name.compareTo(d.name);
}
这将使compareTo()
与equals()
一致(后者现在可以根据前者重写)。此外,如果名称不同,地图将允许具有相同权重的多个条目。
问题内容: 最近在一次求职面试中,有人问我以下问题(对于Java): 鉴于: 的返回值是多少 我回答它会返回false,因为它们是两个不同的对象,并且==是内存地址比较而不是值比较,并且需要使用.equals()比较String对象。但是我被告知,尽管.equals(0方法论是正确的,但是该语句仍然返回true。我想知道是否有人可以向我解释为什么它是正确的,但是为什么我们还在学校里教我们使用equ
如何使用Comparator对对象的ArrayList进行正确排序,然后将排序后的数组传递给自定义数组适配器? 我试过这样做: ArrayList的内容类: 比较器: 在OnCreate中设置适配器: ...因为我使用的是定制的ArrayAdapter,就像: 我需要如何修改此适配器以使其与其他适配器一起工作? 谢谢你的帮助。
我已经被覆盖了hashcode和equals以查找具有相同开始日期和关闭日期的值。我得到了重复对象的类似哈希代码。当等同于这些对象时,我得到了布尔值“假”。在我的理解中,对象==对象比较对象的引用,即使引用是相同的;代码返回假。你能帮我理解是什么问题吗?我在下面发布了我的代码: Main.java 输出: 检查客户对象引用:Customer@643 对象引用(位于Map中):[Customer@6
我需要整理一份arrayList。我可以使用比较器并重写比较函数进行排序。或者我可以自己编写一个合并排序函数,对ArrayList进行排序。 我在某处读到比较器排序使用冒泡排序算法。因为合并排序的复杂度较低,所以我选择合并排序,而不是使用更容易实现的比较器。
我想使用比较器对String类型的ArrayList进行排序。我只找到了如何在ArrayList存储对象时执行此操作的示例。 我有一个包含10个符号的字符串数组列表,最后5个符号是数字。我想按照每个字符串末尾的数字的升序来求解数组列表。我该怎么做? 谢谢
我希望有一个更具体的可比接口,以便我可以更好地键入返回参数。该界面目前如下所示: 现在,当我尝试对这些更具体的可比值列表进行排序时,如下所示,我收到一个错误,因为b的类型是“RankComparable”而不是类型“T”。 为了解决这个问题,我可以实现如下所示的Self方法。这将解决我的问题,但它看起来非常丑陋。如果有人能找到解决这个问题的更好的办法,我会很高兴。