본문 바로가기
IT/Java

equals 와 hashCode의 재정의를 같이 해야하는 이유

by 성준하이 2022. 4. 26.
반응형

먼저 아래와 같이 클래스를 정의해두고

public class Person {
     private final String name;

     public Person(String name) {
          this.name = name;
     }

     // intellij Generate 기능 사용
     @Override
     public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          Person person = (Person) o;
          return Objects.equals(name, person.name);
     }
}

person클래스에서는 equals만 재정의를 하였고
이어서 생성을 해보았다.

public static void main(String[] args){
     Person person1 = new Person("홍길동");
     Person person2 = new Person("홍길동");

     System.out.println(person1.equals(person2));
}

이렇게 한다면 결과는 두개가 같은값인지에 대해서 생각을 해볼 필요가 있다.
person1과 person2에 대해서는 분명 같은 값이 들어갔고 결과는 true가 나올것이다.

그럼 Hash가 아닌 그냥 일반 List일때의 아래의 결과를 예상해보도록 한다.

public static void main(String[] args) {
     List<Person> person = new ArrayList<>();
     person.add(new Person("name"));
     person.add(new Person("name"));

     System.out.println(person.size());
}

같은 값이 2번 들어가서 List의 size는 2가 나올것이다.

그럼 이어서 중복을 허용하지 않는 Set을 사용하여 다시 코딩을 해보고 결과를 예측해본다.

public static void main(String[] args) {
     Set<Person> person = new HashSet<>();
     person.add(new Person("name"));
     person.add(new Person("name"));

     System.out.println(person.size());
}

이번엔 당연히 결과가 1이 나올것으로 예상이 되지만 결과는 2가 나온다.


hashcode를 equals와 함께 재정의를 하지 않으면 코드가 예상과 다르게 동작하는 이런 문제가 일어난다.
정확히 말하면 Hash를 사용하는 hashset, hashmap, hashtable을 사용할 경우에 발생한다.

값은 같지만 객체의 주소를 가리키는 hash의 값이 다르기 때문이다.
hash의 리턴값이 같아도 equals의 리턴값이 다르면 둘은 다른 객체로 판단하기에 다른값으로 비교되고 그리하여 중복이 배제되는 Set역시 다른값으로 인식을 하여 값이 들어가게 된것이다.

그럼 hashcode의 재정의는 어떻게 되는가 하면
아까 처음에 코드에서 equals를 재정의 코드 바로 아래 hashcode를 재정의하여 return 하는 함수 한줄만 작성해주면 간단히 해결된다.

@Override
public int hashCode() {
     return Objects.hash(name);
}

 

반응형

댓글