Skip to content

Latest commit

 

History

History
47 lines (44 loc) · 3.65 KB

File metadata and controls

47 lines (44 loc) · 3.65 KB

아이템 41 - hashCode의 규약을 지켜라

  • hashCode 함수는 수많은 컬렉션과 알고리즘에 사용되는 자료구조인 해시 테이볼(hash table)을 구축할 때 사용

해시테이블

  • 해시 테이블은각 요소에 숫지를 할당하는 함수가 필요
  • 이 함수를 해시 함수라고 부르며, 같은 요소라면 항상 같은 숫자를 리턴
  • 해시 함수가 다음과 같은 특성을 갖고 있으면 좋음
    • 빠름
    • 충돌이 적음 (다른 값이라면 최대한 다른 숫자를 리턴)
  • 해시 함수는 각각의 요소에 특정한 숫자를 할당하고, 이를 기반으로 요소를 다른 버킷에 넣습음
  • 같은 요소는 항상 동일한 버킷에 넣음
  • 버킷은 버킷 수와 같은 크기의 배열인 해시 데이블에 보관
  • 요소를 추가하는 경우에는 해시 함수로 배치할 버킷을 계산
  • 버킷 안에 요소를 추가 (버킷은 배열처럼 구현)
  • 요소를 찾는 경우에도 해시 함수로 만들어지는 숫자를 활용해 버킷을 찾온 뒤, 버킷 내부에서 원하는 요소를 찾음
  • 코틀린/JVM에 있는 기본 세트(LinkedHashSet)와 기본 맵 (LinkedHashMap)도 이룰 사용
  • 코틀린은 해시 코드를 만들 때 hashCode 함수를 사용

가변성과 관련된 문재

  • 요소가 추가될 때만 해시 코드를 계산함
  • 요소가 변경되어도 해시 코드는 계산되지 않으며, 버킷 재배치도 이루어지지 않음
  • 해시 둥의 ‘mutable 프로퍼티로 요소를 조합하는 자료 구조’에서는 mutable 객체가 사용되지 않음
  • 따라서 세트와 맵의 키로 mutable 요소를 사용하면 안 되며, 사용하더라도 요소를 변경해서는 안됨
  • 이러한 이유로 immutable 객체를 많이 사용

hashCode의 규약

  • hashCod~ 명확한 규약
    • 어떤 객체를 변경하지 않았다면, hashCod터즌 여러 번 호출해도 그 결과가 항상 같아야 함
    • equals 메서드의 실행 결과로 두 객체가 같다고 나온다면, hashCode 메서드의 호출 결과도 같다고 나와야 함
  • hashCode는 equals와 같이 일관성 있는 동작을 해야함
  • 즉, 같은 요소는 반드시 같은 해시 코드를 가져야 한다는 의미
  • 코틀린은 equals 구현을 오버라이드할 때, hashCode도 함께 오버라이드 하는 것을 추천
  • 필수 요구 사항은 아니지만 제대로 사용하려면 지켜야 하는 요구 사항
    • hashCode는 최대한 요소를 넓게 퍼뜨려야 한다는 것
    • 다른 요소라면 최대한 다른 해시 값을 갖는 것이 좋음

hashCode 구현하기

  • data 한정자를 붙이면, 코틀린이 알아서 적당한 equals와 hashCode 를 정의해줌
  • 다만 equals를 따로 정의했다면, 반드시 hashCode도 함께 정의해 줘야 함
  • 정당한 이유가 없는 이상 hashCode를 따로 정의하지 않는 것이 좋음
  • equals로 같은 요소라고 판정되는 요소는 hashCode가 반드시 같은 값을 리턴해야 함
  • hashCode는 기본적으로는 equals에서 비교에 사용되는 프로퍼티를 기반으로 해시 코드를 만들어야 함
  • 해시코드 생성법
    • 일반적으로 모든 해시 코드의 값을 더함. 더하는 과정마다 이전까지의 결과에 31을 곱한 뒤 더해줌
    • 관례적으로 31을 많이 사용
  • 코틀린 stdlib이 이러한 함수를 기본적으로 제공하지 않는 이유는 사실 hashCode를 우리가 직접 구현할 일이 거의 없기 때문
  • hashCode를 구현할 때 가장 중요한 규칙은 ‘언제나 equals와 일관된 결과가 나 와야 한다'
  • 같은 객체라면 언제나 같은 값을 리턴하게 만들어 주세요.