Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Java: Java, contains, hashCode, equals, collection

Может ли возникнуть ситуация, когда объект есть в коллекции, но contains возвращает false, и почему?

Вопрос проверяет понимание работы метода contains в Java коллекциях, особенно важное для корректной работы с коллекциями объектов.

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

Да, такая ситуация возможна, если объект был изменён после добавления в коллекцию, и эти изменения повлияли на результаты методов equals и hashCode. Метод contains полагается на эти методы для поиска объекта. Например, если объект является ключом в HashMap и его hashCode изменился, containsKey может не найти его, так как поиск будет вестись по новому хэшу, а объект лежит в корзине со старым.

Длинный ответ

Метод contains в коллекциях Java (таких как ArrayList, HashSet, HashMap) использует методы equals и hashCode для определения наличия объекта. Ситуация, когда объект физически присутствует в коллекции, но contains возвращает false, возникает, если состояние объекта изменилось так, что нарушились контракты этих методов.

Ключевые причины

  • Изменение полей, влияющих на hashCode/equals: Если объект-ключ в HashSet или HashMap изменяется после добавления, его хэш-код может измениться. Поиск в хэш-таблице происходит по новому хэш-коду, который ведёт в другую корзину (bucket), где объект отсутствует.
  • Нарушение контракта между equals и hashCode: Если методы equals и hashCode не согласованы (например, equals сравнивает по одному полю, а hashCode вычисляется по другому), то объект может быть найден по одному критерию, но не по другому.
  • Использование mutable объектов в качестве ключей: Это классическая ошибка, особенно с коллекциями, основанными на хэшировании.

Пример кода

import java.util.HashSet;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // Геттеры и сеттеры
    public void setAge(int age) { this.age = age; }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return 31 * name.hashCode() + age;
    }
}

public class Main {
    public static void main(String[] args) {
        HashSet set = new HashSet<>();
        Person john = new Person("John", 25);
        set.add(john);
        System.out.println(set.contains(john)); // true

        // Меняем поле, влияющее на hashCode и equals
        john.setAge(30);
        System.out.println(set.contains(john)); // false! Объект всё ещё в set, но contains не находит.
    }
}

В этом примере после изменения возраста хэш-код объекта john изменился. HashSet ищет объект в корзине, соответствующей новому хэш-коду, но объект остался в корзине для старого хэш-кода, поэтому contains возвращает false.

Где это применяется и как избежать

Эта проблема критична при использовании пользовательских объектов в качестве ключей в HashMap, HashSet, ConcurrentHashMap или элементах в HashSet. Чтобы избежать этого:

  • Сделайте объекты неизменяемыми (immutable), если они используются как ключи.
  • Если изменение необходимо, удалите объект из коллекции перед изменением и вставьте снова.
  • Убедитесь, что поля, используемые в equals и hashCode, не изменяются после добавления объекта в коллекцию.

Вывод: Ситуация возможна при изменении mutable объектов в хэш-коллекциях, что нарушает механизм поиска. Используйте immutable объекты для ключей или строго контролируйте их изменение, чтобы избежать ошибок.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Java

    Java

Ключевые слова

#Java

#contains

#hashCode

#equals

#collection

Подпишись на Java Developer в телеграм