[java] equals / hashcode에 관한 고찰

CodeKong의 기술 블로그·2024년 3월 22일
2

JAVA

목록 보기
1/5
post-thumbnail

객체가 같은 지 비교하기 위한 방법으로는 equal과 hashcode가 있습니다.

1) equal

equal은 객체의 주소 값을 비교하는 메서드입니다.
하지만 논리적으로 같은 객체를 비교해야 할때는 어떻게 할까요?

Member m1 = new Member("웰시");
Member m2 = new Member("웰시");

m1과 m2는 '논리적'으로는 같은 객체이지만 다른 주소값을 갖습니다

그렇기 때문에 m1.equals(m2)의 결과는 false입니다.


그럼 과연 어떻게 두 객체가 같은지 검증할까요?

모든 객체는 Object 클래스를 상속합니다.
자동적으로 equal 메소드를 상속받습니다.

때문에 equal 메소드의 로직을 주소 값을 비교하는 것이 아니라 내부 값을 비교하는 로직으로 바꾸어주면 해결됩니다. (대표적으로 String 클래스)

class Member {
    private String name;

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true; // 두 객체의 주소가 같으면 바로 true 반환
        if (obj == null || getClass() != obj.getClass()) return false; // null이거나 타입이 다르면 false 반환

        Member member = (Member) obj; // Object 타입의 obj를 Member 타입으로 캐스팅
        return name.equals(member.name); // 두 객체의 name 필드를 비교
    }
}

하지만 여기서도 문제가 발생합니다.


2) hashCode

Hashcode는 객체의 주소를 기반으로 생성된 고유한 정수 값입니다.
이 값은 해시 테이블이나 딕셔너리 같은 자료구조에서 객체를 식별하고, 검색 속도를 최적화하는 데 중요한 역할을 합니다.

이때

"해시 테이블이나 딕셔너리 같은 자료구조에서 객체를 식별"하는 과정

에서 문제가 발생합니다.

Hash~ 부류의 자료구조에서 같은 객체인지 검증하는 순서입니다.

이와 같이 equals에서 동등하다고 hashcode가 동등할지는 모릅니다.

따라서 euqals 뿐만 아니라 hashcode 또한 오버라이딩 해줘야 합니다.

// hashCode() 메서드도 함께 오버라이드하는 것이 좋습니다.
    @Override
    public int hashCode() {
        return Objects.hash(name);
    }

결론

객체의 물리적 동일성과 논리적 동일성의 구분

두 객체가 메모리 상에서 서로 다른 위치(주소)에 있더라도,
객체가 가지고 있는 값이나 상태를 기반으로 같다고 판단할 수 있는 개념을 이해합니다.

hashCode 메소드와 그 중요성

Java에서 equals 메소드를 오버라이드할 때는 hashCode 메소드도 함께 오버라이드해야 합니다.
이는 equals 메소드로 두 객체가 같다고 판단되면, 이 두 객체의 hashCode 메소드가 반환하는 값도 동일해야 한다는 규약 때문입니다.
이 규약을 지키지 않으면, 해시 기반의 컬렉션(예: HashSet, HashMap)에서 예상치 못한 동작이 발생할 수 있습니다.

0개의 댓글