Почему HashSet не распознаёт уже добавленный объект

В исправленном синтаксически фрагменте contains(person) должен вернуть true: тот же неизменённый объект только что добавлен в HashSet. Показанный код сам по себе не объясняет false.

Короткий ответ

Что ответить на собеседовании

В исправленном синтаксически фрагменте contains(person) должен вернуть true: тот же неизменённый объект только что добавлен в HashSet. Показанный код сам по себе не объясняет false.

Подробный разбор

Ответ с пояснениями

Условие

В примере создаётся экземпляр класса Person, который помещается в HashSet, однако вызов метода contains() для того же объекта возвращает false. Что может быть причиной такого поведения?

public void personTask() {}
    Set<Person> people = new HashSet<>();
    Person person = new Person("Петров", "Петр", "Петрович");
    people.add(person);
    people.contains(person); // returns false

@Data
@AllArgsConstructor
private static class Person {
    private String firstName;
    private String lastName;
    private String middleName;
}

Ответ

В исправленном синтаксически фрагменте contains(person) должен вернуть true: тот же неизменённый объект только что добавлен в HashSet. Показанный код сам по себе не объясняет false.

Lombok @Data генерирует equals/hashCode по полям, и здесь между add и contains поля не меняются. Типичная реальная причина — изменение участвующего в hashCode имени после добавления: объект остаётся в старой корзине. Возможны также несогласованные equals/hashCode или конкурентная модификация вне приведённого примера. В исходнике тело personTask закрыто слишком рано; сначала нужно поместить операции внутрь метода. Делайте ключевые поля неизменяемыми либо удаляйте объект до изменения и добавляйте заново.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее