← 질문 목록
#8깊이 0
equals 재정의 시 hashCode도 바꿔야 하는 이유는?
해시 기반 컬렉션이 두 메서드를 함께 쓰기 때문이다. 하나만 바꾸면 컬렉션이 같은 객체를 다른 객체로 취급한다.
HashMap은 먼저 hashCode로 버킷을 찾고 그 안에서 equals로 비교한다. equals만 재정의하면 논리적으로 같은 두 객체가 서로 다른 버킷으로 흩어진다. equals 비교까지 가지도 못하므로 조회가 실패한다.
- get(key)
그다음은 hashCode입니다. 어느 버킷인지 먼저 정한다
hashCode그다음은 버킷입니다. 그 버킷 안의 후보들만 꺼낸다
버킷그다음은 equals입니다. 후보와 하나씩 견준다. 여기까지 와야 비교가 일어난다
equals
규약은 단방향이다. equals가 true면 hashCode는 반드시 같아야 한다. 반대는 성립하지 않는다. hashCode가 같아도 equals는 false일 수 있고 이게 해시 충돌이다.
주의
실무에서 자주 터지는 자리는 JPA 엔티티다. 식별자가 영속화 시점에 채워지므로 id 기반 hashCode는 저장 전후로 값이 바뀐다. Set에 넣어둔 엔티티를 저장하면 다시 찾지 못하게 된다.
가변 필드를 hashCode에 쓰는 것도 같은 함정이다. 컬렉션에 넣은 뒤 필드를 바꾸면 그 객체는 사실상 사라진다.