본문 바로가기
우아한테크코스 4기/레벨1

[Java] 31이란..

by 나는후니 2022. 2. 28.

흔히 equalshashcode를 함께 재정의 하라는 이야기를 들어봤을 것입니다.

저도 당연히 알고 있었지만,, 조금 더 아는체하기 위해 내부 구현을 뜯어봤습니다.

그러자 등장하는 31.

과연 이 녀석의 정체는 무엇일까요??

equals, hashcode 재정의

Object 명세서에서는 equalshashcode에 대해 다음과 같이 언급하고 있습니다.

  • 동등성 비교에 사용되는 정보가 변경되지 않는다면, hashcode 메서드는 일관되게 같은 값을 반환한다.
  • equals 메서드가 두 객체를 같다고 판단한다면 두 객체의 hashcode값은 같다.
  • 두 객체가 equals 하지 않다고 해서 두 객체의 hashcode가 다를 필요는 없다. (하지만 성능이 떨어진다 -> Linked로 관리할거임 아마 ;;)

즉 동등성 비교에 있어 equalshashcode는 짝꿍이고 VO를 만들생각이라면, 게다가 이걸 Hash Collection의 key로 사용한다면 무조건 재정의 해줘야합니다.

자세하게 어떻게 계산하면 좋을지는 IDE에게 맡긴다고 칩시다. 그런데 대체 31은 어디서 나온걸까요?

Effective Java 왈

조슈아 블로크씨가 말하기를 ..

곱한 숫자를 31로 정한 이유는 31이 홀수이면서 소수이기 때문이다. 만약 이 숫자가 짝수이고 오버플로가 발생한다면 정보를 잃게된다.
소수를 곱하는 것은 명확하지 않지만 전통적으로 그리 해왔다.

이런 ;;;

이걸 보고 과거의 저도 면접에서 "왜 31을 곱해서 구현하냐" 고 묻길래 "관롄데영" 이라고 대답했습니다 ;;

근데,, 진짜 그냥 관례입니다.

그래도 소수 + 홀수를 곱하는 이유는 있습니다.

  1. 짝수를 곱하면 비트의 오른쪽 값이 0으로 채워진다. 해시코드는 다양할수록 좋은데... 0이 많아지면 안돼잇
  2. 소수... 는 뭔가 곱하면 독립적인 값을 줄 것(?) 같음 - 사실 이유 아님 ㅋ

참고로 lombok 라이브러리의 @EqualsAndHashCode는 59를 곱한다

정리

정리하자면 이게 포스팅인가 싶을 정도로 알아낸게 없습니다.
그냥 홀수를 사용하는데 굳이 소수를 쓰고 있고, 짝수를 사용하지 않는 이유는 비트가 0으로 메꿔지기 때문입니다.

그냥 값이 다른 객체마다 다른 hashCode를 반환할 수 있다면 그것으로 좋은 hashCode라는 것 정도만 알아둡시다!!