equals
와hashCode
는 함께 재정의해야 한다!→ 그렇지 않으면, 컬렉션의 원소를 사용할 때 문제 발생함
<aside> <img src="/icons/checkmark_orange.svg" alt="/icons/checkmark_orange.svg" width="40px" />
Object 명세 규약 중 일부
hashCode()
를 중복 호출해도 일관된 값을 반환해야 한다.equals(Object)
가 같다고 판단했다면, hashCode 역시 같다.equals(Object)
가 다르다고 판단했더라도, hashCode 는 같을 수 있다.
</aside>이 중, hashCode 재정의를 잘못했을 때 두 번째 조항이 가장 큰 문제가 된다.
물리적으로 다른 두 객체를 논리적으로 같은 객체다고 할 수 있고, 이는 같은 해시코드를 반환해야 한다. 하지만 잘못된 재정의는 hashCode()
호출 시, 전혀 다르다고 판단하고 서로 다른 값을 반환한다.
Map<Member, String> m = new HashMap<>();
m.put(new Member(1, 26), "승히");
m.get(new Member(1, 26)); // null!
// 서로 다른 두 객체의 해시코드가 다르기 때문
이상적인 해시 함수는 주어진 서로 다른 인스턴스들을 32비트 정수 범위에 균일하게 분배하는 것이다.
다음은 좋은 hashCode를 작성하는 간단한 요령이다:
int 변수 result
선언한 후, 값 a
로 초기화한다.
해당 객체의 나머지 핵심 필드 f
는 각각 다음 작업을 수행한다.
a
를 계산
Type.hashCode(f)
수행equals()
가 필드의 equals()
를 재귀 호출해 비교한다면 → 필드의 hashCode 재귀 호출Arrays.hashCode
사용result
를 해시코드 a
로 갱신result
반환