규약에 의하면 equals() 메소드를 재정의 했을때 hashcode() 메소드도 재정의 해야한다.
Hash를 사용한 Collection(HashMap, HashTable, HashSet, LinkedHashSet등등)은 key를 결정할때 hashCode()를 사용
class User {
String name;
User(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
if (this == obj) {
return true;
}
User that = (User) obj;
if (this.name == null && that.name != null) {
return false;
}
if (this.name.equals(that.name)) {
return true;
}
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
}
왜 31을 사용하였는가?
31은 소수이면서 홀수이기 때문에 선택된 값이다. 만일 그 값이 짝수였고 곱셈 결과가 오버플로되었다면 정보는 사라졌을 것이다. 2로 곱하는 것은 비트를 왼쪽으로 shift하는 것과 같기 때문이다. 소수를 사용하는 이점은 그다지 분명하지 않지만 전통적으로 널리 사용된다. 31의 좋은 점은 곱셈을 시프트와 뺄셈의 조합으로 바꾸면 더 좋은 성능을 낼 수 있다는 것이다(31 * i는 (i « 5) - i 와 같다). 최신 VM은 이런 최적화를 자동으로 실행한다.
소수이면서 홀수이기 때문에 선택된 것입니다.
소수는 1과 자기 자신을 제외한 숫자이기 때문에 Hash하였을 경우 충돌이 가장 적은 숫자입니다.
언제든지 변경될 가능성이 있다고 생각합니다.
equals()를 재정의한다면 side effect를 줄이기 위해서 hashCode()도 재정의하는것이 좋습니다.