tonykang22 / study

0 stars 0 forks source link

[Effective Java] 아이템 11. equals를 재정의하려거든 hashCode도 재정의하라. #51

Open tonykang22 opened 2 years ago

tonykang22 commented 2 years ago

아이템 11. equals를 재정의하려거든 hashCode도 재정의하라.

핵심 정리: hashCode 규약


예시 코드

같은 인스턴스인데 다른 hashCode를 갖는 경우

number1.hashCode()number2.hashCode()는 다르다. 그렇기 때문에 System.out.println(s);에서는 콘솔에 null이 찍히게 된다.

public class HashMapTest {

    public static void main(String[] args) {
        Map<PhoneNumber, String> map = new HashMap<>();

        PhoneNumber number1 = new PhoneNumber(123, 456, 7890);
        PhoneNumber number2 = new PhoneNumber(123, 456, 7890);

        // true
        System.out.println(number1.equals(number2));

        System.out.println(number1.hashCode());
        System.out.println(number2.hashCode());

        map.put(number1, "keesun");
        map.put(number2, "whiteship");

        String s = map.get(new PhoneNumber(123, 456, 7890));

        // null
        System.out.println(s);
    }
}


다른 인스턴스인데 같은 hashCode를 갖는 경우

number1.hashCode()number2.hashCode()는 동일한 값을 갖는다.

핵심 정리: hashCode 구현 방법

  1. 핵심 필드 하나의 값의 해쉬값을 계산해서 result 값을 초기화 한다.
  2. 기본 타입은 Type.hashCode 참조 타입은 해당 필드의 hashCode 배열은 모든 원소를 재귀적으로 위의 로직을 적용하거나, Arrays.hashCode result = 31 * result + 해당 필드의 hashCode 계산값
  3. result를 리턴한다.


예시 코드

전형적인 hashCode()


핵심 정리: hashCode 구현 대안


예시 코드

Guava Library


핵심 정리: 주의 할 것


완벽 공략


완벽 공략 27. 해시맵 내부의 연결 리스트

내부 구현은 언제든지 바뀔 수도 있다.


완벽 공략 28. 스레드 안전

멀티 스레드 환경에서 안전한 코드, Thread-safety


예시 코드

사실 아래의 코드에서는 멀티스레드에 안전하지는 않으나, 계산 값이 언제나 동일하기 때문에 크게 문제는 일어나지는 않으나, 여전히 문제는 문제이기 때문에 예시 코드에서 접하게 되었다.

   private int hashCode;

    @Override public int hashCode() {
            int result = hashCode;
            if (result == 0) {
                result = Short.hashCode(areaCode);
                result = 31 * result + Short.hashCode(prefix);
                result = 31 * result + Short.hashCode(lineNum);
                this.hashCode = result;
            }
            return result;
        }
    }