Menu
Coddy logo textTech

equals() и hashCode()

Часть раздела Объектно-ориентированное программирование путешествия по Java на Coddy — урок 42 из 87.

При сравнении объектов в Java оператор == проверяет, указывают ли две ссылки на одну и ту же область памяти. Чтобы сравнить фактическое содержимое объектов, вам необходимо переопределить метод equals().

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

Метод equals() следует стандартному шаблону: сначала проверьте, является ли это тем же самым объектом, затем проверьте тип и, наконец, сравните соответствующие поля.

Всякий раз, когда вы переопределяете equals(), вы также должны переопределить hashCode(). Это контракт в Java: объекты, которые равны, должны иметь одинаковый хеш-код. Хеш-коллекции, такие как HashMap и HashSet, полагаются на это правило для корректной работы.

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

Утилитарный метод Objects.hash() генерирует хеш-код на основе тех же полей, которые используются в equals(). Если два объекта Person имеют одинаковые name и age, они будут считаться равными и будут генерировать идентичные хеш-коды, что обеспечивает согласованное поведение в коллекциях.

challenge icon

Задание

Легко

Давайте создадим систему учета студентов, которая правильно реализует равенство объектов. Вы создадите класс Student, в котором два студента считаются равными, если у них одинаковый идентификатор студента и имя — независимо от того, являются ли они одним и тем же объектом в памяти.

Вы организуете свой код в двух файлах:

  • Student.java: Создайте класс, представляющий студента с тремя приватными полями: studentId (String), name (String) и gpa (double). Включите конструктор для инициализации всех полей и методы-геттеры для каждого поля.

    Переопределите метод equals() так, чтобы два объекта Student считались равными, если у них одинаковый studentId И одинаковое name. Следуйте стандартному шаблону: проверьте на идентичность ссылок, проверьте на null и тип, а затем сравните соответствующие поля.

    Переопределите метод hashCode(), используя Objects.hash() с теми же полями, которые использовались в equals(). Не забудьте импортировать java.util.Objects в начале вашего файла.

  • Main.java: Оживите ваш класс Student, сравнивая объекты студентов. Вы получите шесть входных данных, представляющих двух студентов: ID, имя и GPA первого студента, а затем ID, имя и GPA второго студента.

    Создайте оба объекта Student, затем выполните три сравнения и выведите результаты:

    1. Выведите "Same reference: ", а затем результат проверки того, равен ли первый студент самому себе (всегда должно быть true)
    2. Выведите "Content equality: ", а затем результат проверки того, равен ли первый студент второму (на основе вашей реализации equals)
    3. Выведите "Hash codes match: ", а затем результат проверки того, совпадают ли хэш-коды обоих студентов

Вы получите шесть входных данных: ID первого студента (String), имя первого студента (String), GPA первого студента (double), ID второго студента (String), имя второго студента (String) и GPA второго студента (double).

Обратите внимание, что когда у двух студентов совпадают ID и имена, и equals() возвращает true, И их хэш-коды совпадают — это контракт, который вы должны соблюдать!

Попробуйте сами

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Считать данные первого студента
        String id1 = scanner.nextLine();
        String name1 = scanner.nextLine();
        double gpa1 = scanner.nextDouble();
        scanner.nextLine(); // поглотить символ новой строки
        
        // Считать данные второго студента
        String id2 = scanner.nextLine();
        String name2 = scanner.nextLine();
        double gpa2 = scanner.nextDouble();
        
        // TODO: Создать два объекта Student, используя входные данные
        
        // TODO: Вывести "Same reference: ", а затем результат проверки, равен ли student1 самому себе
        
        // TODO: Вывести "Content equality: ", а затем результат проверки, равен ли student1 объекту student2
        
        // TODO: Вывести "Hash codes match: ", а затем результат проверки, имеют ли оба студента одинаковый хэш-код
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование