hashCode()와 equals()

강병철·2022년 11월 12일
0

서로 다른 두 인스턴스가 어떤 조건을 만족하는 경우 서로 같은 인스턴스로 판별되게끔 하고 싶다? 그럴 때 오버라이딩 하는 메서드들이다.
VO(값 객체)에서만 사용하는 것이 권장된다.

예를 들어 아래와 같은 클래스가 있을 때

class Point {

	private int a;
	private int b;

	public Point(int a, int b) {
		this.a = a;
		this.b = b;
	}
}

우리는 Point p1 = new Point(1,1)Point p2 = new Point(1,1) 는 좌표(a,b)가 같기 때문에 서로 같은 인스턴스로 판별되기를 원한다고 하자.

두 인스턴스를 비교하는 과정

  1. 우선 hashCode() 를 통해 hash값이 일치하는지 확인한다
    • 해쉬값이 다르면 무조건 다른 인스턴스로 판단된다
    • 해쉬값이 같으면 equals()를 통해 추가적인 판별을 하게된다

      hash값이 다르면 무조건 서로 다른 객체로 판별되고, hash값이 같으면 다를 수도 있고 같을 수도 있다

  2. 1에서 hash값이 달랐다면, equals()에서 정의된 로직에 따라 일치 여부를 추가적으로 판별하게된다.
  3. hashcode()와 equals()의 결과가 모두 일치해야 같은 인스턴스로 판별된다

hashCode()를 오버라이딩 해주지 않으면?

인스턴스의 주소값 만으로 해쉬를 만든다.

그렇기 때문에 인스턴스의 상태(a,b)가 같더라도 해쉬값은 서로 다르게 되어, 서로 다른 인스턴스로 판별된다.
그러면 p1과 p2를 HashSet에 넣어도 중복으로 걸러지지 않으며,
HashMap의 Key로 사용해도 서로 다른 Key로 인식된다.

우리가 원하는건 이게 아니기 때문에 Point 클래스 내에서 아래와 같이 오버라이딩을 해줘야한다

@Override
	public int hashCode() {
		return Objects.hash(a, b);
	}

equals()를 오버라이딩 해주지 않으면?

인스턴스의 주소값으로만 비교한다. (p1 == p2)

그래서 hashCode()를 오버라이딩 하여 상태(a,b)가 같은 두 인스턴스 p1, p2의 해쉬값이 같아졌더라도, equals() 검증 단계에서는 두 주소값이 달라 서로 다른 인스턴스로 판별되어버린다.

역시나 우리가 원하는건 이게 아니기 때문에 equals()에서 상태(a,b)가 같으면 true를 반환하도록 오버라이딩 해야한다

@Override
public boolean equals(Objecto) {
   if (this ==o) {
      return true;
   }
   if (o== null || getClass() !=o.getClass()) {
      return false;
   }
   Point point = (Point)o;
   return a == point.a && b == point.b;
}

IntelliJ Generate 기능 활용

각 메서드의 오버라이딩은 IntelliJ의 Generate 기능(단축키(Mac) : Control + Enter)을 사용하면 쉽게 할 수 있다

0개의 댓글