Java의 ArrayList
클래스는 equals
메서드를 재정의하여 인스턴스의 내용 기반으로 리스트를 비교한다.
즉 두 ArrayList
객체가 동일한 순서와 동일한 요소를 포함하고 있다면 equals
메서드는 true
를 반환한다.
List<String> list1 = new ArrayList<>();
list1.add("A");
list1.add("B");
List<String> list2 = new ArrayList<>();
list2.add("A");
list2.add("B");
System.out.println(list1.equals(list2)); // true
list1
과 list2
는 서로 다른 참조를 갖지만 내용은 동일하므로 equals
메서드의 결과는 true
이다.
Java에서 객체의 equals
메서드는 참조를 비교한다.
따라서 사용자 정의 객체에서 내용 기반의 동등성 비교를 원한다면 equals
를 재정의해야 한다.
public class Person {
private String name;
private int age;
}
이 클래스의 인스턴스 두 개를 생성하고 비교해보면
Person person1 = new Person("p1", 25);
Person person2 = new Person("p1", 25);
System.out.println(person1.equals(person2)); // false
두 객체의 내용은 동일하나 equals
메서드의 결과는 false
이다.
이는 Person
클래스가 equals
를 재정의하지 않았기 때문이다.
equals
를 재정의할 때는 항상 hashCode
도 함께 재정의해야 한당.
그렇지 않으면 객체를 해쉬 기반의 컬렉션에 저장할 때 문제가 발생할 수 있다.
@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 && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
이렇게 equals
와 hashCode
를 재정의하면 Person
클래스의 인스턴스는 내용 기반으로 비교된다.
테스트 작성 시 AssertJ 라이브러리를 사용한다면 isEqualTo
메서드로 두 객체의 동등성을 비교할 수 있다.
이 메서드는 내부적으로 객체의 equals
메서드를 사용하여 두 객체를 비교한다.
List<String> expected = new ArrayList<>();
assertThat(result).isEqualTo(expected);
이 코드는 result
와 expected
리스트의 내용이 동일한지 비교한다.
ArrayList
는 이미 equals
메서드를 적절히 재정의하고 있기 때문에 내용 기반으로 비교된다.