티스토리 뷰


많은 버그가 hashCode 메서드를 재정의하지 않아서 생긴다. equals 메서드를 재정의하는 클래스는 반드시 hashCode 메서드도 재정의 해야 한다. 그렇지 않으면 Object.hashCode의 일반 규약을 어기게 되므로 HashMap, HashSet, Hashtable 같은 hash 기반 컬렉션과 함께 사용하면 오동작하게 된다.

 


일반 규약


같은 객체의 hashCode를 여러 번 호출하는 경우 equals가 사용하는 값이 변경되지 않았다면 언제나 동일한 정수(Integer)가 반환되어야 한다. 단 프로그램이 재시작되었을 경우 같은 값이 나올 필요는 없다.

 

  1. equals 메서드가 같다고 판정한 두 객체의 hashCode 값은 같아야 한다.
  2. equals 메서드가 다르다고 판정한 두 객체의 hashCode 값은 꼭 다를 필요는 없다. 그러나 서로 다른 hashCode 값이 나오면 Hashtable 성능이 향상될 수 있다.

 

중요한 점은 두 번째 규약이다. 만약 hashCode를 재정의 하지 않은 class를 HashMap을 사용하여 객체를 생성할 경우 입력했던 객체와 찾으려는 객체의 멤버 변수가 모두 동일하다고 해도 두 객체의 내용이 같을 뿐 별개의 객체이다.
따라서 hashCode는 다른 값을 반환하게 되고 HashMap에서 찾으려 해도 null 값만 반환하게 된다.  올바르진 않지만 그냥 문제없이 돌아가기만 하는 hashCode를 구현하기는 쉽다.

// 이렇게 구현하지 말자.
@Override
public int hashCode() {
	return 42;
}

하지만 절대 이렇게 구현하면 안 된다.

 

특정 고정값으로 hashCode를 반환하면 두 번째 규약에 어긋나는 것은 아니다. 그런데 모두 같은 hash 값을 가지므로 그냥 리스트를 순차적으로 접근하여 해시 테이블은 결국 연결 리스트가 되어 버린다.

 

좋은 해시 함수는 다른 객체에는 다른 hashCode를 반환하는 경향이 있다. 일반 규약 세 번째 항목에서 언급한 사항이 바로 이것이다. 이상적인 해시 함수는 서로 다른 객체들을 모든 가능한 해시값에 균등하게 배분해야 한다.
JDK 1.7 이상이라면 Objects.hash() 또는 Apache 라이브러리 HashCodeBuilder를 사용하여 hashCode를 재정의 해줘야 한다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함