2015-07-29 10 views
4

У меня есть особое требование, когда мне нужно дедуплировать список объектов на основе комбинации критериев равенства.Java Set с несколькими критериями равенства

например. Два Student объектов равны, если:
1. Имя и идентификатор является одинаковыми или 2. LastName, класса и 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

* «Теперь я не могу переопределить метод hashCode таким образом, чтобы он возвращал одинаковые хэш-коды для двух объектов, которые равны в соответствии с этим методом равных» * Можете ли вы объяснить, почему вы это говорите? – m0skit0

+0

См. Комментарий @ m0skit0. Ваш хэш-код неверен, если он не возвращает одно и то же значение для равных объектов. –

+0

@ m0skit0 Это общий контракт [hashCode] (http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29): 'Если два объекта: равный в соответствии с методом equals (Object), тогда вызов метода hashCode для каждого из двух объектов должен приводить к одному и тому же целочисленному результату. ' –

ответ

0

Вы можете сделать StudentComparable и использовать TreeSet. Простая реализация compareTo может быть:

@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(); 
    } 
} 
+0

Этот ответ можно улучшить, показывая некоторый код. –

0

Вы можете увидеть проблему, как пытается найти объекты, которые равны от бизнеса точки зрения, но по-прежнему разные записи. Так что не отменяет либо equals или hashCode таким образом, что сломается такое важное правило:

Если два объекта равны по методу равных (Object), затем вызова метода Hashcode по каждому из два объекта должны производить одинаковый целочисленный результат.

Вместо этого используйте Set реализацию, которая игнорирует hashCode и позволяет использовать пользовательские Comparator. См. Принятый ответ в TreeSet and hashCode().

 Смежные вопросы

  • Нет связанных вопросов^_^