개발/Java

[Java] HashSet.contains() 를 사용하기 위한 @override hashcode()

YJ_Lee 2022. 4. 30. 10:55

2차원 배열에 대한 좌표 x, y를 필드로 가지는 객체를 생성후 equals() 를 정의했다.

@Override
public boolean equals(Object o) {
    if(o instanceof Pos) {
        Pos p = (Pos) o;
        return this.x == p.x && this.y == p.y;

    } else {
        return false;
    }
}

 

하지만, HashSet.contains() 메서드를 사용할 때, 동일한 좌표를 가지는 객체가 존재하더라도 false를 리턴하였다.

 

HashSet은 내부적으로 HashMap을 사용하며, HashMap은 두 객체가 동일한 키임을 판단할 때, 두 hashcode가 같아야 하며, 두 객체가 동일하거나(== 연산결과가 true) 동등해야한다.(equals() 결과가 true)

 

따라서 equals(), hashcode() 둘 다 정의해주어야 한다.

그런데 (x, y) != (y, x) 인, 두 정수에 대한 hashcode를 어떻게 정의해야하나...?

찾아보니 몇 가지 방법이 있다.

 

1) 단순 계산식

public int hashCode() {
    int hash = 17;
    hash = hash * 31 + field1Hash;
    hash = hash * 31 + field2Hash;
    hash = hash * 31 + field3Hash;
    hash = hash * 31 + field4Hash;
    ...
    return hash;
}

 

2) 메서드 호출식

1에 비해 효율성이 떨어진다.

@Override
public final int hashCode()
{
    final int[] numbers = {x, y};
    return Arrays.hashCode(numbers);
}

 

int형 필드가 두개일 경우는 다음과 같이 간단히 표현할 수 있다.

public int hashCode() {
    return x * 31 + y;
}

 


출처:

https://woodcock.tistory.com/24

https://stackoverflow.com/questions/11742593/what-is-the-hashcode-for-a-custom-class-having-just-two-int-properties