Java设置有多个相等标准

时间:2015-07-29 13:23:51

标签: java hash set hashcode deduplication

我有一个特殊要求,我需要根据相等标准的组合重复删除对象列表。

e.g。如果出现以下情况,则两个Student个对象相等:
1. firstName和id相同OR 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,但这几乎占用了内存的三倍。我正在寻找一种速度更快,内存效率更高的方式,因为我将处理大量的记录。

1 个答案:

答案 0 :(得分:0)

您可以Student Comparable并使用TreeSetcompareTo的简单实现可能是:

@Override
public int compareTo(Student other) {
    if (this.equals(other)) {
        return 0;
    } else {
        return (this.firstName + this.lastName + emailId + clazz + id)
                .compareTo(other.firstName + other.lastName + other.emailId + clazz + id);
    }
}

或者制作您自己的Set实现,例如包含List个不同的Student个对象,每次添加学生时都要检查是否相等。这将O(n)增加复杂性,因此不能被认为是一个好的实现,但编写起来很简单。

class ListSet<T> extends AbstractSet<T> {
    private List<T> list = new ArrayList<T>();

    @Override
    public boolean add(T t) {
        if (list.contains(t)) {
            return false;
        } else {
            return list.add(t);
        }
    }

    @Override
    public Iterator<T> iterator() {
        return list.iterator();
    }

    @Override
    public int size() {
        return list.size();
    }
}