규칙 9. equals를 재정의 할 때는 반드시 hasCode도 재정의 하라

많은 버그는 hashCode 메서드를 재정의하지 않아서 생긴다. equals 메서드를 재정의하는 클래스는 반드시 hashCode 메서드도 재정의 해야한다. 그렇지 않을경우 HashMap,HashSet 등과 같은 해시기반 컬렉션과 함께 사용하면 오작동하게 된다.

hashCode의 일반적인 규약은 다음과 같다.

1.응용프로그램 실행 중에 같은 객체의 hashCode를 여러 번 호출하는 경우 equals가 사용하는 정보들이 변경되지 않았다면 언제나 동일한 정수가 반환되어야 한다. 다만 프로그램이 종료되었다 실행되어도 같은 값이 나올 필요는 없다.
2.equals(Object) 메서드가 같다고 판정한 두 객체의 hashCode값은 같아야 ㅎ나다,
3.equals(Object) 메서드가 다르다고 판정한 두 객체의 hashCode값은 꼭 다를 필요는 없다. 그러나 서로 다른 hashCode 값이 나오면 해시테이블의 성능이 향상될 수 있다.

Object의 hashCode

equals메서드가 논리적으로 같다고 판단한 두 객체라 해도 Object의 hashCode입장에서 보면 공통점이 없는 객체일 뿐이므로 같은정수를 반환하는것이 아닌 무작위로 선택된것같은 수를 반환한다.

좋은 해시함수

좋은 해시함수는 다른 객체에서는 다른 해시코드를 반환하는 경향이 있다. 또한 이상적인 해시 함수는 서로 다른 객체들을 모든 가능한 해시 값에 균등하게 배분해야 한다.
이상적인 해시함수를 만들기 위해서는 아래의 규약을 따르면된다.
책 65p 참고

참고사항

  • 중복필드는 해시코드 계산 과정에서 제외해도 된다.
  • equals계산에 쓰이지 않는 필드는 반드시 제외해야 한다.
  • result를 계산할 때 초기값 17은 임의로 잡은값이다. 이를 통해 해시값(c)이 0인것들도 해시값에 영향을 주게 된다.
  • 절차 2.B에 사용된 곱셈은 필드 순서에 따라 계산 결과가 달라지도록 한다. 따라서 유하한 필드가 여러개 있으면 더 좋은 해시값이 나온다.
  • 31은 소수이면서 홀수이기 때문에 선택된 값이다.(전통적으로 소수가 널리 사용된다. 또한 <<5 -i 연산을 통해 더욱 빠른 성능을 낼 수 있다.
Share