Java hashCode из нескольких полей

Учитывая такой класс:

class MyObject {
  private String id1;
  private String id2;

  @Override
  public boolean equals(Object o) {
    if (o == this) return true;
    if (!(o instanceof MyObject)) {
        return false;
    }
    MyObject other = (MyObject) o;
    return id1.equals(other.id1) || id2.equals(other.id2);
  }
}

Обратите внимание, что равенство не зависит от соответствия обоих полей, любое из полей работает. Какая реализация hashCode была бы подходящей для этого класса?

Я не верю, что есть какой-либо хэш-код, который можно использовать для этого.

Andreas 17.07.2018 18:46

@Andreas, вы могли бы использовать минимум два.

Andy Turner 17.07.2018 18:46

@AndyTurner Нет, не можешь. ["A", "B"] vs ["C", "B"] равны, но младший хэш-код - нет.

Andreas 17.07.2018 18:47

@Andreas Хм, верно. Что ж, вы можете использовать константу ...

Andy Turner 17.07.2018 18:48

@Andreas, но определенно это определение равенства нарушает общий договор о равенстве (в частности, транзитивность).

Andy Turner 17.07.2018 18:49

@AndyTurner Верно, но константа - это не хэш-код. Это будет работать, но в основном превращает HashMap в LinkedList.

Andreas 17.07.2018 18:49

@AndyTurner Согласен. Это нарушает договор equals.

Andreas 17.07.2018 18:50
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
8
7
474
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это недопустимая реализация equals.

В частности, это нарушает требование транзитивности.

Таким образом, вы также не можете реализовать hashCode «правильно», за исключением того, что все экземпляры будут иметь один и тот же хэш-код.

Спасибо. В этом есть смысл.

mkohram 17.07.2018 18:52

Я расширил HashSet <String> и реализовал add и contains для работы с этим. Звучит здесь как правильный ход?

mkohram 17.07.2018 18:54

@mkohram, расширяющий HashSet никогда, кажется правильным, особенно если вы меняете поведение существующих методов.

Andy Turner 17.07.2018 18:56

Как еще вы удалили бы дубликат списка этих объектов?

mkohram 17.07.2018 18:56

Также я не меняю поведение. Просто добавил add(MyObject o) и contains(MyObject o) к HashSet<String>.

mkohram 17.07.2018 18:58

Это все еще звучит так, как будто это не сработает. Вместо этого сделайте, например, Map<String, MyObject> mapFromId1 и Map<String, MyObject> mapFromId2 и проверяйте их оба для каждого нового объекта.

Louis Wasserman 17.07.2018 19:05

@LouisWasserman, вот как в основном выглядят реализации моих add и contains. Он просто абстрагирован, поэтому каждый раз, когда я хочу «добавить» MyObject в набор, мне не нужно делать 2 вставки. Спасибо.

mkohram 17.07.2018 19:09

Вы, не должен, делаете эту абстракцию, а не в том, что притворяется HashSet или Set вообще. Set должны отражать только поведение equals и верный, при этом удовлетворяющее контракту поведение equals.

Louis Wasserman 17.07.2018 19:12

@LouisWasserman Я понимаю, о чем вы говорите. Итак, каждый раз, когда я хочу проверить contains в Map, о котором вы говорили, я бы сделал 2 (или более) проверки кода? Это много повторяющегося кода.

mkohram 17.07.2018 19:28

Или создайте свой собственный класс, который выполняет эти операции за вас, но не претендует на роль Set.

Louis Wasserman 17.07.2018 19:33

Спасибо, вот что я сделаю.

mkohram 17.07.2018 19:36

Другие вопросы по теме