equals를 재정의하려거든 hashCode도 재정의하라
1.hashCode재정의를 잘못했을때 문제되는부분
-->논리적으로 같은 객체는 같은 해시코드를 반환해야한다
Map<PhoneNumber,String> m= new HashMap<>();
m.put(new PhoneNumber(707,867,5309),"제니");
이코드 다음에 get메서드를 실행하면 null을 반환
PhoneNumber클래스는 hashCode를 재정의하지않았기때문에 서로 다른 해시코드를 반환
2.사용해서는 안되는 예
@Override
public int hashCode() { return 42;}
1)모든객체에게똑같은 값만 내어준다
2)해시테이블의버킷하나의 담겨 마치 연결리스트처럼동작
3)평균수행시긴간이 O(1)이 아닌 O(n)으로 느려져서 객체가 많아지게되면 쓸수없게 됨
3.좋은 해시코드를 쓰는 요령
1)int변수 result선언후 값c로 초기화
c는 해당객체의 첫번째 핵심 필드를 단계2.a방식으로 계산한 해시코드
2)해당 객체의 나머지 핵심필드 f 각각에 대해 다음 작업을 수행
(1)기본타입 필드라면 Type.hasCode(f)를 수행
(2) 참조타입 필드면서 equals메서드가 해당 필드의 equals를 재귀적으로 호출해 비교한다면, 이 필드의 hashCode를 재귀적으로 호출
(3)필드가 배열이라면 핵심 원소를 각각 별도 필드처럼 다룬다
모든 원소가 핵심 원소라면 Arrays.hashCode를 사용
3)단계 2.a에서 계산한 해시코드 c로 result를 갱신한다
result=31*result+c;
-->31을 곱하는 이유: 31은 홀수이며 소수이기때문
-->곱할 숫자가 짝수이고 오버플로우 발생시 2를 곱하면 시프트 연산과 같은 결과를 주기때문에 정보를 잃게됨
-->소수를 곱하는것은 전통적으로 해온 방식
4)result를 반환한다.
-->객체가 주로 해시키로 사용될거같다면 인스턴스가 만들어질때 해시코드를 계산
5.성능을높이기위해 해시코드를 계산할때 핵심필드 생략은 안된다
핵심정리
1)equals를 재정의할때는 hashCode도 반드시 재정의
2)재정의한 hashCode는 Object API 규약을 따라야한다
3) 서로다른 인스턴스라면 되도록 해시코드도 서로 다르게 구현해야한다