프로그래밍 언어/JAVA

Java에서 equals 및 hashCode 메소드를 재정의 해야 하는 이유

Rateye 2021. 9. 1. 10:34
728x90
반응형
질문 : Java에서 equals 및 hashCode 메소드를 대체해야하는 이유는 무엇입니까?

최근에이 Developer Works 문서를 읽었습니다.

이 문서는 모두 hashCode()equals() 효과적이고 정확하게 정의하는 것에 관한 것이지만,이 두 가지 메서드를 재정의해야하는 이유를 파악할 수 없습니다.

이러한 방법을 효율적으로 구현하기 위해 어떻게 결정을 내릴 수 있습니까?

답변

Joshua Bloch는 효과적인 자바에 대해 말한다

equals ()를 재정의하는 모든 클래스에서 hashCode ()를 재정의해야합니다. 그렇게하지 않으면 Object.hashCode ()에 대한 일반 계약을 위반하게되어 HashMap, HashSet 및 Hashtable을 포함한 모든 해시 기반 컬렉션과 함께 클래스가 제대로 작동하지 못하게됩니다.

hashCode() 를 재정의하지 않고 equals() Map 을 사용하려고하면 어떤 일이 발생하는지 예를 들어 이해해 보겠습니다.

이와 같은 클래스가 있고 importantField MyClass 두 객체가 동일하다고 가정합니다 (eclipse에 의해 생성 된 hashCode()equals()

public class MyClass {
    private final String importantField;
    private final String anotherField;

    public MyClass(final String equalField, final String anotherField) {
        this.importantField = equalField;
        this.anotherField = anotherField;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((importantField == null) ? 0 : importantField.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        final MyClass other = (MyClass) obj;
        if (importantField == null) {
            if (other.importantField != null)
                return false;
        } else if (!importantField.equals(other.importantField))
            return false;
        return true;
    }
}

이것을 가지고 있다고 상상해보십시오

MyClass first = new MyClass("a","first");
MyClass second = new MyClass("a","second");

equals 만 무시

equals 만 재정의되면 myMap.put(first,someValue) 를 호출하면 먼저 일부 버킷으로 해시되고 myMap.put(second,someOtherValue) 를 호출하면 다른 버킷으로 해시됩니다 (해시 코드가 다르기 때문) hashCode ). 따라서 동일하더라도 동일한 버킷에 해시하지 않기 때문에 맵이이를 인식 할 수 없으며 둘 다 맵에 남아 있습니다.

hashCode() 재정의하는 경우 equals() 를 재정의 할 필요는 없지만 MyClass importantField equals() 재정의하지 않는 경우 동일한 경우에 어떤 일이 발생하는지 살펴 보겠습니다.

hashCode 만 재정의

hashCode 만 재정의하는 경우 myMap.put(first,someValue) 를 호출 할 때 먼저 가져 와서 hashCode 계산하여 지정된 버킷에 저장합니다. myMap.put(second,someOtherValue) 를 호출 할 때 맵 문서에 따라 첫 번째를 두 번째로 바꿔야합니다 (비즈니스 요구 사항에 따라).

그러나 문제는 equals가 재정의되지 않았기 때문에 맵이 second 해시하고 second.equals(k) 가 true k 가 있는지 확인하면서 버킷을 반복 second.equals(first)false 입니다.

분명했으면 좋겠어

출처 : https://stackoverflow.com/questions/2265503/why-do-i-need-to-override-the-equals-and-hashcode-methods-in-java
728x90
반응형