equals()와 hashCode()

zwon·2023년 9월 12일
0

Java

목록 보기
4/4

IDE를 보면 사진과 같이 equals()와 hashCode()를 함께 오버라이딩하게 되어있는데 equals()와 hashCode()가 도대체 무엇인지, 왜 둘이 함께 묶이는지에 대해 알아보자.

equals(Object obj)

  • 매개변수로 객체의 참조변수를 받아서 비교하여 그 결과를 boolean값으로 알려 주는 역할을 하는 메서드
  • 두 객체의 같고 다름은 참조변수의 값으로 판단한다.
public boolean equelas(Object obj) {
	return (this==obj);
}

equals(Object obj) 예시

public class Main {
  public static void main(String[] args) {
    Test test1 = new Test(1);
    Test test2 = new Test(1);

    if (test1.equals(test2)) {
      System.out.println("test1과 test2는 같습니다.");
    } else {
      System.out.println("test1과 test2는 다릅니다.");
    }
  }
}
class Test {
  private int value;
  public Test(int value) {
    this.value = value;
  }
}

결과

test1과 test2는 다릅니다.
  • 서로 다르다고 나온 이유는 test1과 test2는 같은 값 1을 가지고 있을지라도 서로의 주소는 다르기 때문이다.

컴퓨터적인 관점에서보면 서로의 주소가 다르기때문에 서로 다른 객체가 맞다.
서로의 주소가 다르더라도 같은 값을 가지고 있으면 같은 객체로 판단하게 할 수는 없을까?
이때 오버라이딩을 통해서 같은 값을 가지고 있을 경우 같은 객체로 판단하게 할 수 있다.

equals(Object obj) 오버라이딩

public class Main {
  public static void main(String[] args) {
    Test test1 = new Test(1);
    Test test2 = new Test(1);

    if (test1.equals(test2)) {
      System.out.println("test1과 test2는 같습니다.");
    } else {
      System.out.println("test1과 test2는 다릅니다.");
    }
  }
}
class Test {
  private int value;
  public Test(int value) {
    this.value = value;
  }

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Test) {
      return this.value == ((Test)obj).value;
    }
    return false; // 객체의 타입이 Test가 아니면 값을 비교할 필요 없음.
  }
}

IDE가 자동으로 오버라이딩해준 코드

@Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Test test = (Test) o;
    return value == test.value;
  }

equals(Object obj) 오버라이딩 결과

test1과 test2는 같습니다.
  • 오버라딩을 통해 서로 다른 인스턴스일지라도 같은 값을 가지고 있을 때, euqals()로 비교하면 true값을 반환받는다.

hashCode()

  • 해싱 기법에 사용되는 해시 함수를 구현한 메서드
  • 해싱은 다량의 데이터를 저장하고 검색하는데 유용하다. 왜냐하면 해시함수는 찾고자 하는 값을 입력하면 그 값이 저장된 위치를 알려주는 해시코드를 반환한다.
  • Object 클래스에 정의된 hashCode()는 객체의 주소값으로 해시코드를 만들어 반환한다.
  • 그렇기때문에 만약 equals()를 오버라이딩해서 객체의 값이 같은 경우 같은 객체로 판단하는 경우라면 hashCode()도 오버라이딩을 해줘야한다.
  • 왜냐하면 같은 객체라면 같은 해시코드를 가지고 있어야하기 때문이다.

hashCode() 오버라이딩X

public class Main {
  public static void main(String[] args) {
    Test test1 = new Test(1);
    Test test2 = new Test(1);
    
    System.out.println("test1.hashCode() = " + test1.hashCode());
    System.out.println("test2.hashCode() = " + test2.hashCode());
    
    if (test1.equals(test2)) {
      System.out.println("test1과 test2는 같습니다.");
    } else {
      System.out.println("test1과 test2는 다릅니다.");
    }
  }
}

class Test {
  private int value;
  public Test(int value) {
    this.value = value;
  }
  
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Test test = (Test) o;
    return value == test.value;
  }
/
}

hashCode() 오버라이딩X 결과

test1.hashCode() = 918221580
test2.hashCode() = 681842940
test1과 test2는 같습니다.
  • 결과를 보면 두 인스턴스의 해시코드는 다른데 서로 같은 객체라고 나왔다.
  • 위에서도 말했듯이 같은 객체면 같은 해시코드를 가지고있어야한는데 hashCode()를 오버라이딩해주지않아서 서로 다른 해시코드를 가진 객체지만 같은 객체라고 판단했다.
  • 그래서 다음과 같이 hashCode()를 오버라이딩 해줘야한다.

hashCode() 오버라이딩O

public class Main {
  public static void main(String[] args) {
    Test test1 = new Test(1);
    Test test2 = new Test(1);
    
    System.out.println("test1.hashCode() = " + test1.hashCode());
    System.out.println("test2.hashCode() = " + test2.hashCode());
    
    if (test1.equals(test2)) {
      System.out.println("test1과 test2는 같습니다.");
    } else {
      System.out.println("test1과 test2는 다릅니다.");
    }
  }
}

class Test {
  private int value;
  public Test(int value) {
    this.value = value;
  }
  
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Test test = (Test) o;
    return value == test.value;
  }

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

hashCode() 오버라이딩O 결과

test1.hashCode() = 32
test2.hashCode() = 32
test1과 test2는 같습니다.

String

  • String은 문자열 내용이 같으면 같은 동일한 해시코드를 반환하도록 hashCode()가 오버라이딩되어있다. 그래서 Java에서 문자열의 내용을 비교하려면 equals()를 사용해서 비교해야한다.

이처럼 객체의 값으로 객체의 같고 다름을 판단하는 경우에는 hashCode()도 함께 오버라이딩해야한다.
되도록이면 맨 위 사진처럼 IDE의 자동화를 사용하자.. 실수할 수도 있으니..

profile
Backend 관련 지식을 정리하는 Back과사전

0개의 댓글

관련 채용 정보