Menu
CoddyTech

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 одинаковые имя и возраст, они будут считаться равными и будут иметь одинаковые хеш-коды, что обеспечивает согласованное поведение в коллекциях.

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 для сравнения объектов студентов. Вы получите шесть входных данных, представляющих двух студентов: сначала идентификатор, имя и средний балл первого студента, затем идентификатор, имя и средний балл второго студента.

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

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

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

Обратите внимание: когда у двух студентов совпадают идентификаторы и имена, 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Проверьте себя

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

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

Потренируйтесь самостоятельно: Онлайн-компилятор Java