Почему List.equals() не работает?

    @Data
    static class Answer {
        private List<Integer> answer;
    }

@PostMapping("/{id}/solve")
 public Response solveQuiz(@PathVariable long id, @RequestBody Answer answer) {
        var rightAnswer = quizService.getQuizByIndex(id).getAnswer();
        var checkAnswer = answer.getAnswer();

        System.out.println(rightAnswer.equals(checkAnswer) ? "equals" : "NOT EQUALS");

        System.out.println(Arrays.equals(rightAnswer.toArray(), checkAnswer.toArray())  ? "equals" : "NOT EQUALS");

        for (int i = 0; i < rightAnswer.size(); ++i) {
            System.out.println(
                    String.format("comparing %d and %d. Res = %s",
                            rightAnswer.get(i), checkAnswer.get(i), rightAnswer.get(i).equals(checkAnswer.get(i))));
        }

Вывод следующий:

RightAnswer [1, 2, 3]
Answer [1, 2, 3]
Hibernate: select quiz0_.id as id1_0_0_, quiz0_.text as text2_0_0_, quiz0_.title as title3_0_0_ from quiz quiz0_ where quiz0_.id=?
NOT EQUALS
Hibernate: select answer0_.quiz_id as quiz_id1_1_0_, answer0_.answer as answer2_1_0_ from quiz_answer answer0_ where answer0_.quiz_id=?
equals
comparing 1 and 1. Res = true
comparing 2 and 2. Res = true
comparing 3 and 3. Res = true

Не совсем понимаю, почему List.equals() считает, что два списка не равны. Помогите пожалуйста.


Ответы (2 шт):

Автор решения: Roman-Stop RU aggression in UA

Типы не совпадают. List это всего лишь интерфейс, реальные объекты разные. hibernate можнет возвращать очень разные типы в зависимости от мапинга.

Нужно проверять, что элементы совпадают. Наиболее правильным способом будет в классе Answer добавить правильную реализацию equals:

@Data
static class Answer {
    private List<Integer> answer;
    @Override
    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;  
        
        if(obj == null || obj.getClass()!= this.getClass())
            return false;
        
        Answer other = (Answer) obj;
          
        return new HashSet<>(getAnswer()).equals(new HashSet<>(other.getAnswer()));
    }

    // также нужно определить hashCode
}

Это будет работать если getAnswer() в quiz возвращает Answer, если нет, нужно сделать чтоб так было. Для этого придется определить конвертор для поля в hibernate.

→ Ссылка
Автор решения: Vladimir Kreslin

А если использовать Arrays.deepEquals() ?

Arrays.deepEquals(rightAnswer.toArray(), checkAnswer.toArray());

→ Ссылка