我有一个TreeMap,其中RobotKey是一个由字符串字段域和长字段时间戳组成的类。 RobotKey具有如下可比性:
@Override
public boolean equals(Object obj) {
if (this.domain.equals(((RobotKey) obj).getDomain()))
return true;
return false;
}
树图根据以下compareTo函数排序:
@Override
public int compareTo(RobotKey arg0) {
if (this.lastAccessed < arg0.lastAccessed)
return -1;
else if (this.domain.equals(arg0.getDomain()))
return 0;
else
return 1;
}
基本上,地图是通过域名访问的,并根据时间戳进行排序。
我做了treemap.get(RobotKey e),其中e与treemap中的现有条目具有相同的域名,但具有不同的时间戳。这应该返回正确的RobotValue,因为Map操作是用equals完成的。但它反而返回null表示找不到RobotKey。知道为什么会这样吗?我做错了什么,我该如何解决?谢谢!
答案 0 :(得分:5)
问题是你的equals和compareTo方法的不一致。
当且仅当compareTo
返回true时,equals
必须返回0,据我所知,TreeMap(或TreeSet)不会调用equals
方法,它只使用compareTo
及其结果表示重复的密钥。
答案 1 :(得分:2)
每当你覆盖equals时,你也应该覆盖hashCode。
在the documentation中查看equals和hashCode的合同,其中If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
您的实现已损坏,因为映射使用hashCode来确定对象所属的存储桶,然后THEN可以使用equals来确定对象是否在存储桶中。在您的情况下,您认为相同的两个对象会生成不同的哈希码,因此集合不会在同一个桶中查找。