Book/이펙티브 자바
Item11 - equals를 재정의하려거든 hashCode도 재정의하라(2)
발망생
2023. 11. 22. 23:25
좋은 해시 함수라면 서로 다른 인스턴스에 다른 해시코드를 반환한다. 이상 적인 해시 함수는 서로 다른 인스턴스들을 32bit 정수 범위에 균일하게 분배해야 한다. 다음은 좋은 hashCode를 작성하는 간단한 요령이다.
public final class PhoneNumber {
private final short areaCode, prefix, lineNum;
public PhoneNumber(int areaCode, int prefix, int lineNum) {
this.areaCode = rangeCheck(areaCode, 999, "area code");
this.prefix = rangeCheck(prefix, 999, "prefix");
this.lineNum = rangeCheck(lineNum, 9999, "line num");
}
... 코드 생략
// 코드 11-2 전형적인 hashCode 메서드 (70쪽)
@Override public int hashCode() {
//기본 타입 필드라면 Type.hashCode(f)
int result = Short.hashCode(areaCode);
result = 31 * result + Short.hashCode(prefix);
result = 31 * result + Short.hashCode(lineNum);
return result;
}
}
파생 필드는 해시코드 계산에서 제외해도 된다. 도한 equals 비교에 사용되지 않는 필드는 '반드시' 제외해야 한다.(규약 두 번째)
클래스가 불변이고 해시코드를 계산하는 비용이 크다면, 매번 새로 계산하기 보다는 캐싱하는 방식을 고려해야 한다. 해시의 키로 사용되지 않는 경우라면 hashCode가 지연 초기화 전략을 사용할 수 있다.(스레드 세이프하게)
private int hashCode; // 자동으로 0으로 초기화된다.
@Override public int hashCode() {
int result = hashCode;
if (result == 0) {
result = Short.hashCode(areaCode);
result = 31 * result + Short.hashCode(prefix);
result = 31 * result + Short.hashCode(lineNum);
hashCode = result;
}
return result;
}