Java HashSet с использованием настраиваемого класса в качестве ключа: функция "contains ()" всегда возвращает false

Я пытаюсь использовать HashSet, используя свой собственный класс «Inner» в качестве типа ключа, как показано ниже:

import java.util.HashSet;
class Inner {
    int i;
    String s;
    public Inner(int i, String s) {
        this.i = i;
        this.s = s;
    }
    @Override
    public int hashCode() {
        return super.hashCode();
    }
    @Override
    public boolean equals(Object o) {
        Inner inner = (Inner) o;
        return i == inner.i && s.equals(inner.s);
    }
}

public class testEquals {
    public static void main(String [] args) {
        HashSet<Inner> hi = new HashSet<>();
        hi.add(new Inner(1,"abc"));
        System.out.println(hi.contains(new Inner(1,"abc")));
    }
}

Он печатает "ложь"

(1) Мой вопрос в том, что пока я пытаюсь использовать функцию «содержит», мне приходится создавать новый объект из «внутреннего» класса для запроса, но поскольку это новый объект, hashcode () отличается. Поэтому я всегда получаю «ложь» для функций «содержит».

(2) Если я изменю hashCode () так, чтобы он возвращал «true», например, equals, когда значения одинаковы, тогда в других сценариях ссылки на разные объекты рассматриваются как «==», как одна уникальная ссылка.

(1) и (2) кажутся противоречащими друг другу.

Как это решить?

Спасибо!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
147
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Вы должны переопределить hashCode таким образом, чтобы два одинаковых объекта имели одинаковый hashCode.

Например:

@Override
public int hashCode() {
    return Objects.hash(i,s);
}

Я не уверен, в чем ваша проблема с (2). Если два объекта равны согласно equals(), HashSet должен рассматривать их как идентичные объекты, даже если это не так.

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

  1. Вы должны правильно переопределить hashCode(), не нарушая контракт равных хэш-кодов.

The contract between equals() and hashCode() is:

  1. If two objects are equal, then they must have the same hash code.
  2. If two objects have the same hash code, they may or may not be equal.
  1. hashCode() не возвращает истину, он возвращает значение типа int. Поэтому просто убедитесь, что он возвращает одно и то же значение int для двух разных объектов, чей equals() возвращает true.

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