我想将数据存储在地图中,关键是unicity,但我希望地图使用我的密钥类的equals方法。
似乎HashMap没有使用equals方法(我可能错了,如果是这样我的测试是错误的。)
我的问题是地图使用hashCode来检查重复,我想要一个使用equals的地图实现。
我将时间戳存储在密钥中,并且如果时间戳差异不超过定义的数量(假设1000毫秒),则希望使2个密钥等于。
编辑:代码
public class CleanKey
{
private DateTime start;
private DateTime end;
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((end == null) ? 0 : end.hashCode());
result = prime * result + ((start == null) ? 0 : start.hashCode());
return result;
}
public boolean equals(Object obj)
{
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
CleanKey other = (CleanKey) obj;
if(end == null)
{
if(other.end != null)
return false;
}
else if(Math.abs(Millis.millisBetween(end, other.end).getMillis()) > 1000)
return false;
if(start == null)
{
if(other.start != null)
return false;
}
else if(Math.abs(Millis.millisBetween(start, other.start).getMillis()) > 1000)
return false;
return true;
}
}
答案 0 :(得分:11)
似乎HashMap不使用equals方法(我可能错了,如果是这样我的测试是错误的。)
确实使用equals
,但它首先使用hashCode
。它只会在具有相同哈希码的密钥上调用equals
- 这就是它如何有效地工作。只要您的hashCode
和equals
方法遵守java.lang.Object
中指定的合同,这就不是问题。
我将时间戳存储在密钥中,并且如果时间戳差异不超过定义的数量(假设1000毫秒),则希望使2个密钥等于。
你做不到。它违反了平等合同,因为你不具备传递性。假设我们有三个密钥x,y和z,并带有以下时间戳:
x 400
y 1200
z 2000
根据您的说明,x.equals(y)
为真,y.equals(z)
为真,但x.equals(z)
为假,因此违反了Object.equals
的合同。
equals方法在非null对象引用上实现等价关系:
- reflexive :对于任何非空引用值x,x.equals(x)应返回true。
- 对称:对于任何非空引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true。
- transitive :对于任何非空引用值x,y和z,如果x.equals(y)返回true而y.equals(z)返回true,则返回x。 equals(z)应该返回true。
- 一致:对于任何非空引用值x和y,x.equals(y)的多次调用始终返回true或始终返回false,前提是在equals比较中没有使用的信息对象被修改。
- 对于任何非空引用值x,x.equals(null)应返回false。
答案 1 :(得分:0)
你需要在你的类中覆盖hashCode和equals。
此处:Understanding the workings of equals and hashCode in a HashMap
看到代码后编辑:
Hashcode返回错误的值,因为您正在使用结束字段来计算哈希...不同的结尾导致不同的哈希。
只是试一试...返回一个常量,hashmap将起作用