【发布时间】:2015-10-20 12:14:11
【问题描述】:
我有一个特殊要求,我需要根据相等标准的组合对对象列表进行重复数据删除。
例如两个 Student 对象相等,如果:
1. firstName 和 id 相同或 2. lastName、class 和 emailId 相同
我打算使用Set 删除重复项。但是,有一个问题:
我可以覆盖equals 方法,但hashCode 方法可能不会为两个相等的对象返回相同的哈希码。
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if ((firstName.equals(other.firstName) && id==other.id) ||
(lastName.equals(other.lastName) && class==other.class && emailId.equals(other.emailId ))
return true;
return false;
}
现在我不能重写 hashCode 方法,因为它会根据 equals 方法为两个相等的对象返回相同的哈希码。
有没有一种基于多个相等标准的重复数据删除方法?我考虑使用List,然后使用contains 方法检查元素是否已经存在,但这增加了复杂性,因为包含在O(n) 时间内运行。我不想为所有对象返回完全相同的哈希码,因为这只会增加时间并超出使用哈希码的目的。我也考虑过使用自定义比较器对项目进行排序,但这至少需要 O(n log n),再加上一次遍历以删除重复项。
到目前为止,我最好的解决方案是维护两个不同的集合,每个条件一个集合并使用它来构建一个List,但这几乎需要三倍的内存。我正在寻找一种更快且内存效率更高的方法,因为我将处理大量记录。
【问题讨论】:
-
“现在我不能重写 hashCode 方法,让它根据这个 equals 方法为两个相等的对象返回相同的哈希码” 你能解释一下你为什么这么说吗?
-
查看@m0skit0 的评论。你的哈希码是错误的,如果它没有为相等的对象返回相同的值。
-
@m0skit0 那是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 合约,我的问题是实现它有什么问题。
-
@m0skit0 在我的 equals 方法中有一个 if-else 语句,所以
hashCode和equals永远不会同步。考虑这个例子,如果我使用所有五个字段来计算hashCode,equals将仅基于其中两个或三个。所以例如如果firstName和id相同,则对象相等,但其他三个值可能不同,因此这两个对象的 hashCode 也将不同。你可以试着去实现,你就会明白我在说什么。
标签: java hash set hashcode deduplication