두 객체가 같은 내용을 가지는지 확인 하기 위해서는, equals()
를 다음의 로직으로 재정의한다.
1. 두 객체의 참조값을 비교한다.
2. 다르다면? 두 객체가 같은 클래스인지 비교한다.
3. 다르다면? 두 객체가 가진 멤버 변수 값이 각각 모두 같은지 비교한다.
이렇게 재정의를 마치면, 다음의 경고를 볼 수 있다.
왜 hashCode()
도 재정의하라는 걸까?
그 이유는 equals()
가 true로 나오는 두 객체는 hashCode()
도 반드시 같아야하기 때문이다.
hash 값을 사용하는 Collection(HashSet, HashMap, HashTable)은 다음의 과정으로 두 객체가 같은지 판단한다.
1. hashCode()
비교
2. 같으면? equals()
비교
따라서 equals()
가 두 객체의 주소가 아닌 내용을 비교하도록 재정의하였다면, 기본적으로 객체의 주소값으로 해시코드를 생성하는 hashCode()
도 반드시 이와 같은 규칙을 따르도록 재정의해줘야한다.
💡
equals()
이전에hashCode()
로 먼저 비교하는 이유
equals()
내부에서 두 객체가 가진 멤버 변수 값이 각각 모두 같은지 비교하는 과정이 많은 비용을 야기시킨다.
예를들어, A클래스 타입의 두 객체를 비교하려고 하는데 A클래스가 멤버 변수로 B클래스를 가지고 있다면? B클래스 또한 멤버 변수로 C클래스를 가지고 있다면? 두 객체 비교하기위해 굉장히 많은 연산을 수행해야하는 복잡한 상황이 연출된다.
따라서, 두 객체 비교시hashCode()
의 리턴 값 즉, 각자의 멤버 변수들을 연산하여 생성한 해시코드를 비교하여 다르면 먼저 걸러주는 것이 더 효율적이다.
예를 들어 hashCode()
를 재정의할 때, 매개변수로 주어진 값들을 이용해서 고유한 해시코드를 생성하는 Objects.hash()
에 클래스의 멤버 변수들을 인자로 전달하여 리턴받은 해시코드를 반환하도록 정의한다.
Reference