hashCode()와 equals()의 차이 와 역할

hashCode()와 equals()의 차이 와 역할
HashSet 과 HashMap 은 JDK 에서 가장 많이 사용 되 는 두 가지 유형 으로 HashSet 은 같은 대상 을 저장 할 수 없 도록 요구 하고 HashMap 은 같은 키 를 저장 할 수 없 도록 요구 합 니 다.  그렇다면 자바 가 실 행 될 때 환경 은 HashSet 의 같은 대상,HashMap 의 같은 키 를 어떻게 판단 합 니까?'같은 것'을 저장 한 후에 자바 가 실 행 될 때 환경 은 어떻게 유지 합 니까?  이 문 제 를 연구 하기 전에 먼저 JDK 가 equals(Object obj)와 hashcode()두 가지 방법 에 대한 정의 와 규범 을 설명 합 니 다.  자바 의 모든 대상 은 equals(Object obj)와 hashcode()두 가지 방법 을 가지 고 있 습 니 다.왜냐하면 그들 은 Object 류 에서 정의 되 기 때 문 입 니 다.  equals(Object obj)방법 은 두 대상 이'동일'한 지 판단 하 는 데 사용 되 며,'동일'하면 true 로 돌아 가 고,그렇지 않 으 면 false 로 돌아 갑 니 다.  hashcode()방법 은 int 수 를 되 돌려 줍 니 다.Object 클래스 의 기본 값 은'이 대상 의 내부 주 소 를 정수 로 변환 하여 되 돌려 줍 니 다'입 니 다.  그 다음 에 두 가지 방법 에 관 한 중요 한 규범 이 있다.  규범 1:equals(Object obj)방법 을 다시 쓰 려 면 hashcode()방법 을 다시 써 서 equals(Object obj)방법 으로 결 과 를 true 로 판단 하 는 두 대상 이 같은 hashcode()반환 값 을 가지 고 있 는 지 확인 할 필요 가 있 습 니 다.쉽게 말 하면"두 대상 이 같다 면 그들의 hashcode 는 같 아야 한다"는 것 이다.그러나 주의:이것 은 규범 일 뿐 입 니 다.만약 당신 이 equals(Object obj)를 true 로 되 돌려 주 고 hashcode()는 서로 다른 두 값 을 되 돌려 주 려 고 한다 면 컴 파일 과 실행 은 틀 리 지 않 을 것 입 니 다.그러나 이렇게 자바 규범 을 위반 하면 프로그램 도 BUG 를 묻 게 된다.  규범 2:equals(Object obj)가 false 로 돌아 가면 두 대상 이'다르다'는 것 입 니 다.이 두 대상 에 대해 hashcode()방법 으로 두 개의 다른 수 를 얻 으 라 고 요구 하지 않 습 니 다.간단하게 말하자면,"만약 두 대상 이 같 지 않다 면,그들의 hashcode 는 같 을 수 있다."  이 두 가지 규범 에 따라 다음 과 같은 추론 을 얻 을 수 있다.  1.만약 에 두 대상 이 equals 라면 자바 가 실 행 될 때 환경 은 그들의 hashcode 가 반드시 같다 고 생각 합 니 다.  2.두 대상 이 equals 가 아니라면 그들의 hashcode 는 같 을 수 있 습 니 다.  3.만약 에 두 대상 의 hashcode 가 같다 면 그들 은 반드시 equals 가 아니다.  4.만약 에 두 대상 의 hashcode 가 같 지 않 으 면 그들 은 반드시 equals 가 아 닐 것 이다.  이렇게 하면 자바 가 실 행 될 때 환경 이 HashSet 과 HastMap 의 두 대상 이 같 거나 다르다 는 것 을 어떻게 판단 하 는 지 추측 할 수 있다.내 추측 은 hashcode 가 같은 지 아 닌 지 를 판단 한 다음 에 equals 여 부 를 판단 하 는 것 이다.  테스트 프로그램 은 다음 과 같 습 니 다.우선 hashCode()와 equals(Object obj)방법 을 정의 합 니 다. 
자바 코드   
class A {  
  
    @Override  
    public boolean equals(Object obj) {  
        System.out.println("  equals");  
        return false;  
    }  
  
    @Override  
    public int hashCode() {  
        System.out.println("  hashcode");  
        return 1;  
    }  
}

 
그리고 테스트 클래스 를 작성 합 니 다.코드 는 다음 과 같 습 니 다. 
자바 코드
public class Test {  
  
    public static void main(String[] args) {  
        Map<A,Object> map = new HashMap<A, Object>();  
        map.put(new A(), new Object());  
        map.put(new A(), new Object());  
          
        System.out.println(map.size());  
    }  
      
}

 
실행 후 인쇄 결 과 는:  판단 hashcode  판단 hashcode  판단 equals  2  자바 가 실 행 될 때 환경 이 new A()라 는 대상 의 hashcode()방법 을 호출 하 는 것 을 알 수 있 습 니 다.그 중:  인쇄 된 첫 번 째 줄'판단 hashcode'는 첫 번 째 map.put(new A(),new Object()에서 인쇄 된 것 입 니 다.  다음'판단 hashcode'와'판단 equals'는 두 번 째 map.put(new A(),new Object()에서 인쇄 되 었 습 니 다.  그렇다면 왜 이런 인쇄 결과 일 까?나 는 이렇게 분석 했다.  1.첫번째 map.put(new A(),new Object()가 실 행 될 때 환경 은 이 map 에 현재 추 가 된 new A()대상 과 같은 키 가 있 는 지 판단 합 니 다.판단 방법:new A()대상 의 hashcode()방법 을 호출 하여 map 에 현재 new A()대상 과 같은 HashCode 가 존재 하 는 지 판단 합 니 다.분명히 이 때 는 같은 것 이 없 었 다.왜냐하면 이 맵 에는 아직 물건 이 없 었 기 때문이다.그래서 이때 hashcode 가 같 지 않 으 면 없습니다.
equals(Object obj)방법 을 다시 호출 해 야 합 니 다.추론 4 참조(두 대상 hashcode 가 같 지 않 으 면 그들 은 반드시 평등 하지 않 을 것 이다)  2.두 번 째 map.put(new A(),new Object()를 실 행 했 을 때 자바 가 실 행 될 때 환경 이 다시 판단 하 는 것 을 발 견 했 습 니 다.이때 map 에 똑 같은 hashcode(A 류 의 hashcode()방법 을 다시 썼 기 때문에 equals(Object obj)방법 으로 판단 할 필요 가 있 습 니 다.추론 3(만약 두 대상 의 hashcode 가 같다 면 그들 은 반드시 equals 가 아니다)을 참고 한 후에 두 대상 이 equals 가 아니 라 는 것 을 발견 했다.(내 가 equals(Object obj)방법 을 다시 썼 기 때문에 영원히 false 로 돌아 갈 것 이다.)  3.이때 판단 이 끝나 고 판단 결과:두 번 입 금 된 대상 은 같은 대상 이 아니다.그래서 마지막 으로 맵 의 길 이 를 인쇄 할 때 결 과 는 2 입 니 다.  리 셋 프로그램 은 다음 과 같 습 니 다. 
import java.util.HashMap;  
import java.util.Map;  
  
  
class A {  
  
    @Override  
    public boolean equals(Object obj) {  
        System.out.println("  equals");  
        return true;  
    }  
  
    @Override  
    public int hashCode() {  
        System.out.println("  hashcode");  
        return 1;  
    }  
}  
  
  
public class Test {  
  
    public static void main(String[] args) {  
        Map<A,Object> map = new HashMap<A, Object>();  
        map.put(new A(), new Object());  
        map.put(new A(), new Object());  
          
        System.out.println(map.size());  
    }  
      
}

자바 코드
실행 후 인쇄 결 과 는:  판단 hashcode  판단 hashcode  판단 equals  1  분명히 이때 맵 의 길 이 는 1 이 되 었 습 니 다.자바 가 실 행 될 때 환경 이 똑 같은 대상 두 개 를 저장 했다 고 생각 하기 때 문 입 니 다.원인 은 상술 한 분석 방식 에 근거 하여 분석 할 수 있다.  이상 에서 분석 한 것 은 HashMap 이다.사실 HashSet 의 밑바닥 자체 가 HashMap 을 통 해 이 루어 진 것 이기 때문에 그의 판단 원 리 는 HashMap 과 같 고 hashcode 를 먼저 판단 한 다음 에 equals 를 판단 한다.  그래서:프로그램 을 쓸 때 가능 한 한 규범 에 따라 야 합 니 다.그렇지 않 으 면 자신 도 모 르 는 사이 에 bug 를 묻 습 니 다!

좋은 웹페이지 즐겨찾기