Правильное использование объектов‑ключей в HashMap

Equals и hashCode должны учитывать одинаковый набор полей Exam. Тогда examTwo заменит значение для ключа, равного examOne, и итоговый HashMap будет содержать три записи, включая null.

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

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

Equals и hashCode должны учитывать одинаковый набор полей Exam. Тогда examTwo заменит значение для ключа, равного examOne, и итоговый HashMap будет содержать три записи, включая null.

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

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

Условие

В примере используется HashMap<Exam, String>, где в качестве ключей выступают экземпляры класса Exam. Необходимо реализовать корректный механизм сравнения объектов Exam, чтобы HashMap правильно обрабатывала повторяющиеся ключи.

import java.util.HashMap;
import java.util.Map;

public class JetbulbInterview {
    public static void main(String[] args) {
        Map<Exam, String> exams = new HashMap<>();

        Exam examOne = new Exam(1, "04.07.2021", 10);
        Exam examTwo = new Exam(1, "04.07.2021", 10);
        Exam examThree = new Exam(3, "04.07.2021", 9);

        exams.put(null, "Zero");
        exams.put(examOne, "One");
        exams.put(examTwo, "Two");
        exams.put(examThree, "Three");

        exams.forEach((k, v) -> {
            System.out.println("Key: " + k);
            System.out.println("Value: " + v);
        });
    }
}
class Exam {
    long id;
    String date;
    int mark;

    public Exam(long id, String date, int mark) {
        this.id = id;
        this.date = date;
        this.mark = mark;
    }

    @Override
    public String toString() {
        return "Exam{" +
                "id=" + id +
                ", date='" + date + '\'' +
                ", mark=" + mark +
                '}';
    }
}

Ответ

Equals и hashCode должны учитывать одинаковый набор полей Exam. Тогда examTwo заменит значение для ключа, равного examOne, и итоговый HashMap будет содержать три записи, включая null.

Внутри Exam:

@Override
public boolean equals(Object other) {
    if (this == other) return true;
    if (other == null || getClass() != other.getClass()) return false;
    Exam e = (Exam) other;
    return id == e.id && mark == e.mark && java.util.Objects.equals(date, e.date);
}
@Override
public int hashCode() {
    return java.util.Objects.hash(id, date, mark);
}

Значения итоговых записей: Zero для null, Two для экзамена с id=1 и Three для id=3. Порядок обхода не гарантирован. Поля ключа лучше final: изменение их после put нарушает ожидаемый поиск в хеш-таблице.

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

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

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

Подробнее