equals()와 hashCode

박태현·2025년 4월 18일

Java

목록 보기
8/17

equals()


== 연산자 : 기본형 비교 시 값을 비교, 객체 비교 시 주소 값으로 비교

equals() 메서드 : 기본적으로 객체의 주소 값으로 비교


값 타입의 동등성 비교에는 == 연산자를 사용할 수 있지만, 객체의 동등성 비교는 기본적으로 메모리 주소값을 기준으로 이루어지므로, 필드 값을 기준으로 객체의 동등성을 판단하려면 equals() 메서드를 오버라이딩하여 사용해야합니다.

equals() 오버라이딩 ⭐

class Person {
    String name;

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

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

				// false, == 은 객체 타입인 경우 주소값을 비교
        System.out.println(person1 == person2);

				// false, equals() 또한 객체 타입인 경우 주소값을 비교
        System.out.println(person1.equals(person2)) 
    }
}

객체를 비교할 때 주소값이 아니라 필드 값을 비교하도록 동동 비교 기준을 변경하고 싶다면 , equals() 메서드를 오버라이딩하여 재정의해야합니다.

class Person {
    String name;

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true; // 자신과 비교하면 true
        if (!(o instanceof Person)) return false; // 같은 타입이 아닌 경우 false
        
        // 같은 타입인 경우 다운캐스팅하여 필드 값 비교
        Person person = (Person) o; 
        return Objects.equals(this.name, person.name);
    }
}

hashCode() 메서드


객체의 고유한 정수 값( 주소 값으로 만든 고유한 숫자 값 )을 반환하는 메서드

자바에는 equals() 비교가 true인 두 객체는 hashCode() 값 또한 같아야한다는 규약이 있으므로, equals()를 재정의한다면 hashCode() 또한 재정의해야합니다.

만약 하지 않는다면 Hash를 사용하는 컬렉션에서는 중복을 검사할 때 hash 값을 사용하기에 문제가 발생할 수 있습니다

equals()만 재정의 한다면, 두 객체의 해시코드가 다르지만, 논리적으로 같은 객체로 판단됨

만약 hashSet에서 논리적으로 같은 두 객체를 추가한다고 할 때, 두 객체는 논리적으로는 같지만 해시 코드가 다르기에 컬렉션에 중복된 데이터가 들어가는 문제가 발생


hashCode 재정의

class Person {
    public String name;

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person p = (Person) o;
        
        return Objects.equals(name, p.name);
    }
		
		// 주소 값이 아닌, 필드의 값을 통해 해시 값 생성
		// Objects.hash(...)를 통한 구현은 내부적으로 배열을 사용하므로 성능적으로 좋지 않음
    @Override
    public int hashCode() {
        return Objects.hash(name); // name 필드의 해시코드를 반환
    }
    
    // 성능이 민감한 클래스 hashCode 재정의
    @Override
	public int hashCode() {
	    int result = name.hashCode();
	    result = 31 * result;
	    
	    return result;
	}
}
profile
꾸준하게

0개의 댓글