java - 예제 - 자바 클래스 비교




equals()와 hashCode()가 동기화되도록하는 방법은 무엇입니까? (3)

Guava testlib 라이브러리에는 equals()hashCode() 구현에 대한 테스트를 작성하는 데 사용할 수있는 EqualsTester 라는 클래스가 있습니다.

테스트를 추가하면 코드가 지금 올바른지 확인하고 나중에 수정할 때 코드가 올바른지 확인하는 데 도움이됩니다.

우리는 equals ()와 hashCode ()를 계산하기 위해 매우 복잡한 논리를 요구하는 클래스를 작성하고 있습니다. 줄을 따라 뭔가 :

@Getters @Setters @FieldDefaults(level=AccessLevel.PRIVATE)
public class ExternalData {
  TypeEnum type;
  String data;
  List<ExternalData> children;
} 

우리는 이러한 객체를 구성하지 않으며, 외부의 복잡한 시스템에서 XML로 비 직렬화됩니다. 20 개 이상의 유형이 있으며 형식 데이터에 따라 무시하거나 자식으로 처리하거나 자식없이 처리 할 수 ​​있으며 각 노드 유형에 대한 데이터 비교는 유형에 따라 다릅니다.

모든 규칙을 반영하기 위해 equals () 및 hashCode ()를 만들었지 만 hashCode가 equals와 동기화되지 않아 동일한 객체가 HashSet에 두 번 추가되는 문제가 발생했습니다. HashMap (및 그 문제에 대한 HashSet)은 Java에서 다음과 같이 구현됩니다. https://en.wikipedia.org/wiki/Hash_table 구현은 먼저 객체를 hashCode를 기반으로 버킷에 놓은 다음 각 버킷 검사 equals에 대해 버립니다. 2 개의 동일한 객체가 다른 버킷으로 이동하는 불행한 시나리오에서는 equals ()로 비교되지 않습니다. 여기서 "싱크가 맞지 않음"은 다른 버킷에 들어가는 것을 의미합니다.

equals와 hashCode가 동기화되지 않도록하는 가장 좋은 방법은 무엇입니까?

편집 :이 질문은 Java에서 equals 및 hashCode를 재정의 할 때 고려해야 할 문제점은 무엇입니까? 거기서 그들은 일반적인 지침에 대해 물었고 나의 대답은 받아 들여지지 않았습니다. 그들은 "equals와 hashCode를 일관성있게 만드십시오"라고 말하면서, 내가 정확히 어떻게 그렇게하는지 묻습니다.


condsider에 대한 하나의 옵션은 코드 생성 일 수 있습니다. 기본적으로 비교할 필요가있는 것들의리스트를 작성하고 equals 메소드와 hashcode 메소드를 생성하는 프로그램을 가지고 있습니다. 비교할 동일한 목록에서 두 방법을 모두 생성하므로 동기화되지 않아야합니다 (개별 요소가 물론 제공되지는 않음).


a.equals(b) 경우 a.hashcode() == b.hashcode() 합니다.

그러나 조심하십시오 . !a.equals(b)a.hashcode() != b.hashcode() 의미하지 않습니다 .

이것은 해시 충돌이 알고리즘 및 많은 요인에 따라 심각한 문제가 될 수 있기 때문입니다. 일반적으로 두 객체가 같은 경우 해시 코드는 항상 동일합니다. 그러나 a.hashode() == b.hashcode()a.equals(b) 의미하지 않으므로 두 객체가 해시 코드를 비교하는 것만으로 동등한 지 확인할 수는 없습니다 .







hashcode