equals를 재정의한 클래스는 hashCode도 재정의 해야한다.
그렇지 않는다면 hashCode 일반 규약을 어기게 되어 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으키기 때문이다.
Map<PhoneNumber, String> map = new HashMap<>();
map.put(new PhoneNumber(010,1111,1111), new Person("테스트"));
이 코드에 map.get(new PhoneNumber(010,1111,1111))을 실행하면 테스트값이 아닌 null 값을 반환한다.
이유는 PhoneNumber클래스에 hashCode를 재정의 하지 않았기 때문에, 다른 해시코드를 반환하기 때문이다.
hashMap은 해시코드가 다른 엔트리 끼리는 비교를 시도조차 하지 않도록 최적화 되어 있다.
좋은 해시코드는 서로 다른 인스턴스 마다 다른 해시코드를 반환하는 것이 이상적인 해시 함수 이며, 32비트 정수 범위에 균일하게 분배되어야 한다.
1.int 변수인 result를 선언한 후 값을 c로 초기화한다.
전형적인 hashCode 메서드
@Override
public int hashCode() {
int result = Integer.hashCode(areaCode);
result = 31 * result + Integer.hashCode(prefix);
result = 31 * result + Integer.hashCode(lineNum);
return result;
}
PhoneNumber 핵심 필드 3개를 이용해 간단한 계산만 수행하고, 이 과정에 비결정적 요소는 전혀 없다.
-> 동치 이기 때문에 PhoneNumber 인스턴스는 서로 같은 해시코드를 가질 것이 확실하다.
equals를 재정의할 때는 hashCode를 반드시 재정의해야 하며, 그렇지 않으면 프로그램이 제대로 동작하지 않을것이며, 서로 다른 인스턴스라면 되도록 해시코드가 서로 다르게 구현해야한다.