Почему 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());