객체의 동등성 비교

parkrootseok·2025년 2월 5일

자바

목록 보기
10/19
post-thumbnail

동등성 비교

Java에서 equlas()hashCode()는 객체의 동등성을 비교할 때 사용하는 메소드 입니다. equals()는 두 객체가 논리적으로 동일한지 비교하고, hashCode()는 객체를 빠르게 검색하기 위해 해시값을 반환합니다. Java의 Object 클래스는 기본적으로 이 두 메서드를 제공하며, 필요에 따라 재정의해야 합니다.

equals()란?

equals()Object 클래스에 구현되어 있는 메서드이며, 두 객체가 동일한지 비교하는 역할을 수행합니다. 또한, 모든 클래스는 기본적으로 Object를 상속받고 있습니다.

기본 구현 방식

Object 클래스에서 기본적으로 제공하는 equals()는 다음과 같이 동일한 참조인지 확인하는 기능을 수행합니다.

@Override
public boolean equals(Object obj) {
    return (this == obj);
}

equals() 재정의가 필요한 이유

equals() 재정의는 객체의 내용을 비교하기 위해 필요합니다.

다음과 예시와 같은 경우 재정의를 수행하지 않는다면, 객체에 대한 상태가 같아도 참조하는 곳이 달라 일치하지 않다는 결과과 나옵니다.


// 2명의 유저가 존재하고, 이 둘의 이름은 같습니다.
User user1 = new User(1, "root");
User user2 = new User(1, "root");

// eqauls()를 재정의 하지 않은 경우
user1.equals(users2); -> false

하지만, User가 가진 상태가 동일한 경우 같은 객체로 봐야하는 상황이라면 이와 같은 수행 결과가 나와서는 안됩니다. 이를 위해 다음 예시와 같이 메소드를 재정의할 수 있습니다.

class User {
	
    private String id;
	private String name;

	User(String id, String name) {
    	this.id = id;
        this.name = name;
    }
    
    @Override
    public boolean equals(Object obj) {
    	
        // 참조가 같을 경우 동일
    	if (this == obj) return true;
        
        // null 또는 클래스가 다를 경우 동일하지 않음
        if (obj == null || getClass() != obj.getClass()) return false;
        
        User user = (User) obj;
        return Objects.equals(id,  user.id);
	
    }
    
}

위와 같이 재정의를 수행하게 되면 두 유저의 id가 같은 경우 동일한 객체라고 판단할 수 있게됩니다.

재정의 시 주의 사항

equal()에 대한 재정의를 수행할 때 다음과 같은 사항들을 고려해야 합니다.

  • 반사성
    • x.equals(x) -> 항상 true
  • 대칭성
    • x.equals(y)와 y.equals(x)는 동일한 결과
  • 추이성
    • x.equals(y)와 y.equals(z)의 결과가 동일하다면, x.eqauls(z)도 동일한 결과
  • 일관성
    • x.equals(y)의 결과는 객체의 변화가 없다면 동일
  • NULL 비교
    • x.equals(NULL) -> 항상 false

hashCode()란?

hashCode()Object 클래스에 구현되어 있는 메서드이며, 해시 기반 컬렉션에서 객체를 빠르게 검색하기 위한 해시값을 반환하는 역할을 수행합니다. 또한, 모든 클래스는 기본적으로 Object를 상속받고 있습니다.

기본 구현 방식

Object 클래스에서 기본적으로 제공하는 hashCode()는 다음과 메모리 주소를 기반으로 해시값을 반환합니다.

public int hashCode() {
    return System.identityHashCode(this);
}

하지만, 두 객체의 주소가 아닌 정보를 바탕으로 동등성을 비교하고 있다면 위와 같이 사용할 경우 두 객체에 대한 해시값은 다르게 나올 것 입니다. 그렇기에 다음과 같이 재정의하는 작업이 필요합니다.

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

이에 따라, id가 같은 경우 동일한 해시값을 가지게 됩니다.

재정의 시 주의 사항

hashCode()에 대한 재정의를 수행할 때 다음과 같은 사항들을 고려해야 합니다.

  • x.equals(y)결과가 true 이면, x.hashCode() == y.hashCode()
    • 단, 역은 성립하지 않음
  • hashCode()가 달라도, equals()는 반드시 false는 아님
  • hashCode()가 같아도, equals()는 반드시 true는 아님

equals()와 hashCode()의 관계

두 메서드의 관계는 다음과 같습니다.

  • x.equals(y)결과가 true 이면, x.hashCode() == y.hashCode()
    • 단, 역은 성립하지 않음
  • 해시 기반 컬렉션을 사용할 때 필수적으로 함께 재정의 필요
    • equals()만 재정의 -> 다른 객체로 인식하여 중복 저장
    • hashCode()만 재정의 -> 객체를 찾을 수 없음

예상 질문

equals()와 hashcode() 메서드의 목적은 무엇인가요?

equals()는 두 객체의 논리적 동등성을 비교하는 메서드이고, hashcode()는 객체를 식별할 수 있는 해시값을 얻기 위한 메서드입니다. 즉, equals는 같은지 여부를 판단하는 것이고, hashcode는 버킷의 위치를 판단하는 용도입니다.

hashcode()의 결과는 어디에 사용하나요?

hashcode() 메서드를 통해 얻은 해시값은 해시 기반 자료구조에서 객체를 저장하거나 조회할 때 버킷 위치를 결정하는데 사용합니다. 만약, 사용자 정의 객체를 해시 기반 자료구조에서 사용할 경우 반드시 equals()와 hashcode() 모두 재정의가 필요합니다.

equals() 결과가 true일 때, hashcode()는 다르다면 어떤 문제가 발생하나요?

해시 기반 자료구조에서 동일한 객체를 다른 객체로 인식하여 중복이 발생할 수 있습니다. 왜냐하면, 해시 기반 자료구는 해시값을 기준으로 버킷을 찾은 후 equals()로 두 객체의 동등성을 비교하기 때문입니다. 따라서, 동일한 객체가 서로 다른 버킷에 저장되어 중복이 발생할 수 있습니다.

profile
동료들의 시간과 노력을 더욱 빛내줄 수 있는 개발자가 되고자 노력합니다.

0개의 댓글