Как переопределить метод хэш-кода в соответствии с этой специальной логикой равенства - PullRequest
2 голосов
/ 26 мая 2020

У нас есть специальный logi c для метода «равно», как показано ниже: Мы используем idTypeA / idTypeB / idType C в качестве ключа для сравнения, только если они не пусты для обоих объектов. Как правильно переопределить метод hashCode, соответственно этот вид равен logi c?

public class Student {
private String idTypeA;
private String idTypeB;
private String idTypeC;
public Student(String idTypeA, String idTypeB, String idTypeC) {
    this.idTypeA = idTypeA;
    this.idTypeB = idTypeB;
    this.idTypeC = idTypeC;
}

@Override
public boolean equals(Object obj) {
    if (obj == null || !(obj instanceof Student)){
        return false;
    }
    Student keyIn = (Student) obj;

    if ((!idTypeA.isEmpty()) && (!keyIn.idTypeA.isEmpty())) {
        if (0 == idTypeA.compareToIgnoreCase(keyIn.idTypeA)) {
            return true;
        } else {
            return false;
        }
    }

    if ((!idTypeB.isEmpty()) && (!keyIn.idTypeB.isEmpty())) {
        if (0 == idTypeB.compareToIgnoreCase(keyIn.idTypeB)) {
            return true;
        } else {
            return false;
        }
    }

    if ((!idTypeC.isEmpty()) && (!keyIn.idTypeC.isEmpty())) {
        if (0 == idTypeC.compareToIgnoreCase(keyIn.idTypeC)) {
            return true;
        } else {
            return false;
        }
    }

    return false;
}

@Override
public int hashCode() {
    // TODO ??? How to correctly override the hashCode method
    // according to above equals method
    return super.hashCode();
}
}

Спасибо,

Frank

Ответы [ 3 ]

3 голосов
/ 26 мая 2020

Этот метод equals не является транзитивным:

  • ("a", "", "c") равно ("a", "b", "c")
  • ("a", "b", "c") равно ("", "b", "d")
  • Но ("a", "", "c") не равно ("", "b", "d")

Это означает, что ваш метод equals не соответствует требованиям по переопределению equals().

Это нормально имеют c специфичных для приложения понятий «равенство» (довольно распространенное - «почти равно»). Но вы просто не можете вписать их в Java * специфические c понятия equals()hashCode), потому что код, основанный на задокументированных свойствах equals (рефлексивность, симметрия, транзитивность и т. Д. c ) не будет вести себя так, как ожидалось.

Таким образом, не имеет смысла спрашивать, как реализовать hashCode(), потому что это тоже не может соответствовать требованиям.

1 голос
/ 26 мая 2020

Основываясь на вашем исходном вопросе и комментариях, обсуждаемых под ним, и ответе Робби, я бы переформулировал ваш вопрос следующим образом: как оптимальным образом управлять набором объектов, имеющих 3 разных ключа, используемых для сопоставления равенства? Поэтому я отвечу на этот вопрос, на случай, если кто-то будет обвинять в том, что не ответил на исходный вопрос.

Мое предложение - создать класс-оболочку для хранения карт размером 3 га sh и сравнения ваших объектов Student с этими 3 строковыми ключами с его помощью.

Вот моя реализация с предположением, что ваши ключи являются полями publi c, а не закрытыми, как указано в исходном сообщении. * и вот код для его тестирования или для понимания того, как я себе представлял его использование:

List<Student> students = new LinkedList();

students.add(new Student("spades", "hearts", "diamonds"));
students.add(new Student("hearts", "diamonds", "clubs"));
students.add(new Student("spades", "diamonds", "hearts"));

StudentX group = new StudentX();
group.bulkAddStudents(students);

Student noob = new Student("diamonds", "clubs", "hearts");  //try different values for proper testing
if (group.findStudent(noob) != null) {
    System.out.println("Student found");
} else {
    System.out.println("Student not found");
}

Надеюсь, это было ясно, что я имел в виду с классом-оболочкой для хранения 3 га sh -карт для оптимального поиска и сравнение.

1 голос
/ 26 мая 2020

Как я вижу, у вас есть два основных c варианта:

  1. Вернуть 0, если один из ключей пуст, и обычный код ha sh на основе ключа значения в противном случае.
    Это может быть неэффективно, если вы ожидаете иметь много пустых ключей, так как большинство операций поиска придется отложить до equals(), чтобы убедиться, что совпадение найдено.
  2. Возвращает случайный ha sh код, если один из ключей пуст, и обычный ha sh код на основе значений ключей в противном случае.
    Это неэффективно, потому что генерация случайных значений требует больших затрат на обработку, но поиск будет быстрым .

Так что это небольшая загвоздка 22. Оба подхода действительны и не нарушают контракт equals() / hashCode(), но имеют разные компромиссы в производительности.

...