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);
    }
}

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

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

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

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

challenge icon

Задание

Легко

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

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

  • Student.java: создайте class, представляющий студента, с тремя закрытыми полями: studentId (String), name (String) и gpa (double). Добавьте constructor для инициализации всех полей и методы getter для каждого поля.

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

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

  • Main.java: оживите ваш class 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, И их хеш-коды совпадают. Именно этот контракт вы должны поддерживать!

REQUIRED OUTPUT FORMAT: [Your translated content here]

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

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: Print "Same reference: " followed by whether student1 equals itself
        
        // TODO: Print "Content equality: " followed by whether student1 equals student2
        
        // TODO: Print "Hash codes match: " followed by whether both students have the same hash code
    }
}
quiz iconПроверьте себя

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

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

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