Подтвердить что ты не робот

Набор Java Set - метод переопределения равным

Есть ли способ переопределить метод equals, используемый типом Set? Я написал собственный метод equals для класса с именем Fee. Теперь у меня есть LnkedList of Fee, и я хочу убедиться, что нет дублированных записей. Таким образом, я рассматриваю возможность использования Set insted a LinkedList, но критерии для определения того, равны ли две сборы, находятся в методе overriden equals в классе Fee.

Если вы используете LinkedList, мне придется перебирать каждый элемент списка и вызывать метод overriden equals в классе Fee, а остальные записи - как параметр. Простое чтение этого звука звучит как слишком большая обработка и добавит сложности вычислений.

Можно ли использовать Set с переопределенным методом equals? Должен ли я?

4b9b3361

Ответ 1

Как сказал Джефф Фостер:

Метод Set.equals() используется только для сравнения двух наборов для равенства.

Вы можете использовать Set, чтобы избавиться от повторяющихся записей, но будьте осторожны: HashSet не использует методы equals() своих содержащихся объектов для определения равенства.

A HashSet содержит внутреннюю запись HashMap с <Integer(HashCode), Object> и использует equals(), а также метод equals HashCode для определения равенства.

Один из способов решения проблемы - переопределить hashCode() в классе, который вы помещаете в Set, чтобы он представлял ваши критерии equals()

Пример:

class Fee {
      String name;

  public boolean equals(Object o) {
      return (o instanceof Fee) && ((Fee)o.getName()).equals(this.getName());
  }

  public int hashCode() {
      return name.hashCode();
  }

}

Ответ 2

Вы можете и должны использовать Set для хранения типа объекта с помощью метода переопределенных равных , но вам также может потребоваться переопределить hashCode(). Равные объекты должны иметь одинаковые хэш-коды.

Например:

public Fee{

    public String fi;

    public String fo;

    public int hashCode(){

        return fi.hashCode() ^ fo.hashCode();
    }

    public boolean equals(Object obj){

        return fi.equals(obj.fi) && fo.equals(obj.fo);
    }
}

(Конечно, с нулевыми проверками).

Установки часто используют hashCode() для оптимизации производительности и будут ошибочно работать, если ваш метод hashCode нарушен. Например, HashSet использует внутренний HashMap.

Если вы проверите исходный код HashMap, вы увидите, что это зависит как от методов hashCode(), так и от equals() элементы для определения равенства:

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

Если хэш не сгенерирован правильно, ваш метод equals никогда не может быть вызван.

Чтобы сделать ваш набор быстрее, вы должны генерировать разные хэш-коды для объектов, которые не равны, где это возможно.

Ответ 3

Set использует метод equals объекта, добавленного в набор. В JavaDoc указано

Коллекция, которая не содержит повторяющихся элементов. Более формально множества не содержат пары элементов e1 и e2 таких, что e1.equals(e2) и не более одного нулевого элемента.

Метод Set.equals() используется только для сравнения двух наборов для равенства. Он никогда не использовался как часть добавления/удаления элементов из набора.

Ответ 4

Одним из решений было бы использовать TreeSet с помощью компаратора.

Из документации:

Экземпляр TreeSet выполняет все сравнения элементов с помощью метода compareTo (или сравнения), поэтому два элемента, которые считаются равными этому методу, равны с точки зрения множества.

Этот подход будет намного быстрее, чем использование LinkedList, но немного медленнее, чем HashSet (ln (n) vs n).

Стоит отметить, что один из побочных эффектов использования TreeSet заключается в том, что ваш набор будет отсортирован.