92

나는 많은 장소에서 독서 중에 말하는 것을 읽는다.equalsJava에서 메서드를 재정의해야합니다.hashCode방법도 그렇지 않으면 "계약 위반"입니다.

그러나 지금까지 hashCode 메서드가 아니라 equals 메서드 만 재정의하면 어떤 문제도 발생하지 않았습니다.

계약이란 무엇입니까? 그리고 내가 계약을 위반할 때 어떤 문제에 직면하지 않는 이유는 무엇입니까? hashCode 메서드를 재정의하지 않은 경우 어떤 경우에 문제가 발생합니까?


  • 이 " 계약 " 그게 아무것도 아냐.시행하다그것. 당신이 그것을 깨면 아무것도 즉시 부서지지 않습니다. 그러나다른 코드계약의 일부를 수행하지 않으면 개체를 처리하는 "무료"기능이 "중단"됩니다. 그리고 그러한 개체를 사용하려고 할 때 정확히 어떤 일이 발생합니까?HashMap. - Joachim Sauer
  • javaworld.com/article/2074996/… - Sasikumar Murugesan

7 답변


129

당신이 가질 수있는 문제는 요소의 단일성이.equals().hashCode()예를 들어,HashMap.

이름에서 알 수 있듯이 해시 테이블에 의존하며 해시 버킷은 개체의 함수입니다.hashCode().

두 개의 객체가있는 경우.equals(),하지만 다른 해시 코드를 가지고, 당신은 잃는다!

여기서 중요한 계약 부분은 다음과 같습니다.있는 개체.equals()반드시 같아야한다..hashCode().

이것은 모두에 설명되어 있습니다에 대한 javadocObject. 과조슈아 블로흐네가해야한다고 했어.효과적인 자바. 충분했다.


  • 짧고 " Nuff said " +1 - ManishS
  • @ 혼란 하나의 혼란이 있는데 왜 HashMap의 경우 hashCode 메서드를 재정의 할 때 equals 메서드를 재정의해야합니까? . 임의의 해시 코드에서 객체의 해시 코드가 동일한 경우 값을 바꿉니다. - Vikas Verma
  • @VikasVerma 아니, 아니야; 먼저, 키의 해시 코드가 계산되고 올바른 버킷이 동등 함을 위해 쿼리됩니다. .equals ()를 재정의하지 않으면 같은 해시 코드를 가진 두 객체가 같지 않은 상황에 놓일 수 있습니다. 이는 .equals ()의 기본 구현이 참조 평등 (즉,==). - fge

14

이 문서에 따르면, hashCode의 기본 구현은 모든 객체마다 다른 정수를 반환합니다.

꽤 현실적이지만, Object 클래스에 의해 정의 된 hashCode 메소드는   별개의 객체에 대해 고유 한 정수를 반환합니다. (이것은 일반적으로   객체의 내부 주소를 정수로 변환하지만이 구현

기술은 JavaTM 프로그래밍 언어에서 필요하지 않습니다.

그러나 어떤 때는 해시 코드가 동일한 의미를 갖는 다른 객체에 대해 동일하게되기를 원합니다. 예를 들어

Student s1 = new Student("John", 18);
Student s2 = new Student("John", 18);
s1.hashCode() != s2.hashCode(); // With the default implementation of hashCode

이러한 종류의 문제는 HashTable, HashSet과 같은 컬렉션 프레임 워크에서 해시 데이터 구조를 사용하는 경우 발생합니다.특히 HashSet과 같은 콜렉션에서는 중복 요소가 생겨 Set 계약을 위반하게됩니다.


10

예, 무시해야합니다. 재정의해야한다고 생각하는 경우equals(), 그럼 당신은 재정의해야합니다.hashCode()그 반대. 일반 계약해시 코드():

  1. Java 어플리케이션의 실행 중에 같은 오브젝트로 2 회 이상 불려 갈 때마다 hashCode 메소드는, 오브젝트의 equals 비교로 사용 된 정보가 변경되지 않으면, 같은 정수를 일관되게 돌려 줄 필요가 있습니다. 이 정수는 응용 프로그램의 한 실행에서 동일한 응용 프로그램의 다른 실행으로 일관성을 유지할 필요가 없습니다.

  2. 2 개의 객체가 equals (Object) 메소드로 동일하면, 2 개의 객체의 각각으로 hashCode 메소드를 호출하면 (자), 같은 정수 결과가 생성되지 않으면 안됩니다.

  3. equals (java.lang.Object) 메소드로 2 개의 객체가 동일하지 않은 경우, 2 개의 객체의 각각으로 hashCode 메소드를 호출하면, 다른 정수 결과가 생성 될 필요는 없습니다. 그러나 프로그래머는 부동 한 객체에 대해 고유 한 정수 결과를 생성하면 해시 테이블의 성능이 향상 될 수 있음을 인식해야합니다.


5

만나다의 JavaDocjava.lang.Object

에서hashCode()그것은 말한다 :

두 객체가equals(Object)방법,   그 다음에hashCode각 객체에 대한 메소드절대로 필요한 것   같은 정수 결과를 내다.

(나에 의한 강조).

재정의하는 경우에만equals()하지hashCode()학급이이 계약에 위배됩니다.

이것은 또한 JavaDoc에서equals()방법:

일반적으로 다음을 무시해야합니다.hashCode방법   이 메소드가 오버라이드 (override) 될 때마다, 일반적으로   계약을 맺다hashCode메서드는 동일한 객체가   동일한 해시 코드를 갖는다.


4

계약은obj1.equals(obj2)그때obj1.hashCode() == obj2.hashCode()맵은 주로 hashCode 메소드를 사용하여 항목 키를 비교하므로 주로 성능상의 이유로 사용됩니다.


  • if obj1! = obj2then obj1.hasCode ()! = obj2.hashCode () < - 참이 아님! 서로 다른 해시 코드를 가질 수 있지만 이것은아니요건 - fge
  • @ 맞아, 해시 코드가 충돌 할 수있어. 편집 해. - gma

3

계약은 다음과 같습니다. 두 객체가 같으면 동일한 해시 코드를 가져야하며 두 객체가 같지 않으면 동일한 해시 코드를 가질 수도 있고 그렇지 않을 수도 있습니다.

HashMap에서 객체를 키로 사용해보십시오 (joachim-sauer의 의견에 따라 편집). 문제가 발생하기 시작합니다. 계약은 지침이며 강제적 인 것은 아닙니다.


  • " 있어야 함 " = > " 있어야 함 "을 사용해야하며 "열쇠in HashMap ". - Joachim Sauer

3

좀 봐.Hashtables,Hashmaps,HashSets기타 등등. 그들은 모두 해시 키를 키로 저장합니다. 호출 할 때get(Object key)매개 변수의 해시가 생성되고 지정된 해시에서 조회됩니다.

덮어 쓰지 않을 때hashCode()키의 인스턴스가 변경되었습니다 (예를 들어 전혀 문제가되지 않는 간단한 문자열).hashCode()동일한 객체에 대해 2 개의 서로 다른 해시 코드가 생길 수 있으며 이로 인해 제공된 키를 찾을 수 없습니다.map.get().

연결된 질문


관련된 질문

최근 질문