개발/Java

equals()와 hashcode()

jis1218 2024. 11. 30. 23:23

다음과 같은 클래스가 있다고 하자

public class MyClass {

    private String name;
    private String wow;

    public MyClass(String name, String wow) {
        this.name = name;
        this.wow = wow;
    }
}

이 클래스에 대한 인스턴스를 두개 만들고 비교를 하면 false라고 나온다. 그 이유는 Object의 equals는 주소값이 같은지를 확인하기 때문이다. obj1 == obj2

    public static void main(String[] args) {
        MyClass myClass = new MyClass("MyClass", "wow");
        MyClass myClass1 = new MyClass("MyClass", "wow");

        System.out.println(myClass.equals(myClass1)); // false

    }

그러면 System.out.println(myClass.equals(myClass1))가 true를 반환하게 하려면 어떻게 해야할까? equals를 override해야 한다.

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (o == null || getClass() != o.getClass()) {
        return false;
    }
    MyClass myClass = (MyClass) o;
    return Objects.equals(name, myClass.name) && Objects.equals(wow, myClass.wow);
}

equals()를 override 했음에도 문제가 하나 있다. Set을 만들어 두 객체를 add해보자

public static void main(String[] args) {
    MyClass myClass = new MyClass("MyClass", "wow");
    MyClass myClass1 = new MyClass("MyClass", "wow");

    Set<MyClass> set = new HashSet<>();

    set.add(myClass);
    set.add(myClass1);
    
    system.out.println(set.size()) # 2
}

size가 1일 것을 예상했지만 2가 나왔다. 그 이유는 Set의 경우 객체의 hashCode() 값을 비교하기 때문이며 hashCode() 함수는 각 객체의 주소값을 변환하여 생성한 고유의 정수값이다. 따라서 이 hashCode()까지 같게 하려면 override해야 한다.

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

// Objects의 hashCode() 함수
public static int hashCode(Object o) {
    return o != null ? o.hashCode() : 0;
}

// Arrays의 hashCode() 함수
public static int hashCode(Object[] a) {
    if (a == null)
        return 0;

    int result = 1;

    for (Object element : a)
        result = 31 * result + (element == null ? 0 : element.hashCode());

    return result;
}