JavaStudy

ITEM9 : eqauls 메소드를 오버리이드 할때는 hashCode 메소드도 항상 같이 오버라이드 하자

  • equals 를 오버라이드 할떄 hashCode 를 적절하게 오버라이드 해주지 않으면 HashMap HashSet HashTable 을 포함 하는 모든 hash 기반의 컬랙션들과 우리 클래스를 같이 사용할 때 적절하게 동작하지 않을수있다! (해쉬 기반 콜랙션들은 hashCode 함수로 키값을 사용한다)
    • hashCode 는 실행중에 같은 객체에 대해 항상 같은값 호출해야된다. 어플리케이션 재실행때는 달라도됨
    • eqauls 가 true 이면 hashCode 는 반드시 같다
    • eqauls 가 false 라고 해서 hashCode 가 반드시 false 여야 하는건 아니다. 하지만 달라야 해쉬 콜랙션들의 성능을 향상 시킬수 있다.
  • 적절한 해쉬 메소드를 사용하여 hashCode 함수를 구현해주어야한다.

    • f 가 boolean 이면 1 or 0
    • f 가 byte char short int 이면 (int)f
    • f 가 long 이면 (int)(f ^ ( f >>> 32))
    • f 가 float 이면 Float.floatToIntBits(f)
    • f 가 double 이면 Double.floatToLongBits(f) 한후에 long 처럼 해준다.
    • f 가 객체 참조일 경우 eqauls 메소드를 재귀적으로 호출하면 hashCode 메소드도 재귀적으로 자동 호출된다.
    • f 가 배열이라면 배열의 각 요소를 별개의 필드처럼 처리한다. Arrays.hashCode 메소드들 중 하나를 사용할수 있다.
    • result = 31 * result + c, result 초기값 17 소수를 사용해서 해쉬 기능 향상 시킴!
    • equals 메소드에서 비교하지 않은 필드는 hashCode 필드에서 제외시켜야함.

    • 만약 해쉬 코드 연산비용이 중요한 클래스라면 lazy initializtion 을 할수있다.

      @Override public int hashCode() {
        int result = 17;
        result = 31 * result + areaCode; // 모두 short 형
        result =31 * result + prefix;
        result = 31 * result + lineNumber;
        return result;
      }
      
      private volatile int hashCode;
      @Override public int hashCode() {
           int result =hashCode;
           // 한번만  해쉬코드 설정해주고 계속 사용
           if (result == 0) {
             int result = 17;
             result = 31 * result + areaCode; // 모두 short 형
             result =31 * result + prefix;
             result = 31 * result + lineNumber;
             hashCode = result;
           }
           return result;
      }