본문 바로가기
Back-End

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

by 코젼 2025. 3. 13.
728x90
반응형

equals와 hashCode 메서드는 객체의 동등성 비교해시값 생성을 위해서 사용할 수 있다. 하지만, 함께 재정의하지 않는다면 예상치 못한 결과를 만들 수 있다. 가령, 해시값을 사용하는 자료구조(HashSet, HashMap..)을 사용할 때 문제가 발생할 수 있다.

class EqualsHashCodeTest {

    @Test
    @DisplayName("equals만 정의하면 HashSet이 제대로 동작하지 않는다.")
    void test() {
        // 아래 2개는 같은 구독자
        Subscribe subscribe1 = new Subscribe("team.maeilmail@gmail.com", "backend");
        Subscribe subscribe2 = new Subscribe("team.maeilmail@gmail.com", "backend");
        HashSet<Subscribe> subscribes = new HashSet<>(List.of(subscribe1, subscribe2));

        // 결과는 1개여야하는데..? 2개가 나온다.
        System.out.println(subscribes.size());
    }

    class Subscribe {

        private final String email;
        private final String category;

        public Subscribe(String email, String category) {
            this.email = email;
            this.category = category;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Subscribe subscribe = (Subscribe) o;
            return Objects.equals(email, subscribe.email) && Objects.equals(category, subscribe.category);
        }
    }
}

이슈 발생 원인

해시값사용하는 자료구조hashCode 메서드의 반환값을 사용하는데, hashCode 메서드의 반환 값일치한 이후 equals 메서드반환값 참일 때만 논리적으로 같은 객체라고 판단한다.

위 예제에서 Subscribe 클래스는 hashCode 메서드를 재정의하지 않았기 때문Object 클래스기본 hashCode 메서드를 사용한다. -> Object 클래스의 기본 hashCode 메서드는 객체의 고유한 주소사용하기 때문에 객체마다 다른 값을 반환한다.

따라서 2개의 Subscribe 객체는 다른 객체로 판단되었고 HashSet에서 중복 처리가 되지 않는다.

728x90
반응형

'Back-End' 카테고리의 다른 글

동기 방식으로 외부 서비스 호출 시 장애 조치 방안  (0) 2025.03.18
동일성과 동등성의 차이  (2) 2025.03.14
JPA ID 생성 전략  (0) 2025.03.12
로그와 메트릭  (0) 2025.03.11
일급 컬렉션  (0) 2025.03.07

댓글