Always override hashCode when you override equals
- 2판 제목 : equals를 재정의할 때는 반드시 hashCode도 재정의하라
- 3판 제목 : equals를 재정의하려거든 hashCode도 재정의하라
equals
를 재정의한 클래스의 많은 버그가 hashCode
에서 발생한다.
hashCode
재정의는 equals
의 재정의 규약에도 포함되어있는 만큼 누락될 시 HashSet
이나 HashMap
과 같은 컬렉션에서 문제를 일으킬 수 있다.
좀 더 자세히 본다면 아래와 같이 명세할 수 있다.
- 애플리케이션의 실행 중 같은 객체의
hashCode
를 여러 번 호출하는 경우에,equals
가 사용하는 정보들이 변경되지않았다면 항상 같은 값을 반환해야 한다. equals(Object)
메서드가 같다고 판정한 두 객체의hashCode
값은 항상 같아야 한다.equals(Object)
메서드가 다르다고 판단한 두 객체의hashCode
값은 항상 다를 필요는 없다. 하지만 HashTable의 성능을 생각하는 경우 다른 값을 가지는 것이 좋다.
따라서 equals
를 재정의한 클래스는 반드시 hashCode
도 재정의해야한다.
에제를 살펴보자.
1 | public final class PhoneNumber { |
PhoneNumber
클래스를 HashMap
에 넣어서 사용한다고 가정해보자.
1 | Map<PhoneNumber, String> map = new HashMap<>(); |
이후 아래 코드를 출력하면 어떤 값이 나올까?
1 | System.out.println(map.get(new PhoneNumber((short) 707,(short) 867,(short) 5309))); |
기대값은 “Jenny” 겠지만 사실 null이 출력된다.
이는 PhoneNumber
클래스에 hashCode
를 재정의하지 않았기 때문이다.
반대로 hashCode
를 재정의하면 문제는 해결된다.
재정의하는 코드는 아래와 같다.
1 | private volatile int hashCode; |
주의해야할 것은 성능을 개선하기 위해 객체의 중요 부분을 해시코드 계산 과정에서 생략하면 안된다는 것이다.