BackEnd/Java

JAVA equals, hashCode 메소드

Potwings 2023. 5. 18. 23:50

자바에서 모든 객체들이 기본적으로 상속받는 Object 클래스에 기본적으로 equalshashCode 메소드가 존재한다.

 

equals 메소드

두 개의 객체가 동일한지 비교하는데 쓰이는 메소드이다.

기본적으로 두 객체의 주소값이 동일할 경우 true를 return한다.

보통 equals 메소드를 오버라이드객체 내부의 값을 비교하여 동일 여부를 판단하곤 한다.

equals의 기본 내용

 

hashCode 메소드

객체가 저장되어 있는 주소값을 기준으로 hashCode를 생성하여 return 한다.

어플리케이션이 실행되는 동안 하나의 객체는 항상 동일한 hashCode값을 return한다.

 

hashCode native 메소드로 경우 자바가 아닌 C, C++ 같은 네이티브 언어로 작성된 메소드이다.

자바 프로그램에서는 JNI(Java Native Interface)를 통해 호출하여 사용한다. 

 

허나 hashCode값이 동일하다해서 주소값이 동일한 것은 아니다.

 

오버라이딩

우리는 객체를 비교할 때 편리하기 하기 위하여 equals와 hashCode 메소드를 오버라이딩하여 사용할 수 있다.
Lombok을 사용할 경우 @EqualsAndHashCode를 사용하여 편리하게 오버라이딩 할 수 있다.

(Lombok을 사용하지 않을 경우 IDE에서 기본적으로 제공해주는 생성 기능을 사용하면 된다)

@EqualsAndHashCode을 사용한 결과를 디컴파일해보면 아래와 같다.

객체에 @EqualsAndHashCode 추가

 

Overriding 된 equals 메소드

객체의 주소값만 비교하던 기존과 달리 객체 내부의 값이 같을 경우에도 true를 return 해준다.

lombok을 통하여 override한 equals 메소드

 

Overriding 된 hashCode메소드

hashCode 생성 시 객체에 저장되어 있는 값을 기반으로 생성하여 값이 동일할 경우 hashCode값이 동일하게 나온다. 

lombok을 통하여 override한 hashCode 메소드

 

 

참고 - String의 경우 기본적으로 equals와 hashCode가 오버라이딩 되어있다.

String의 equals 메소드
String의 hashCode 메소드

 

 

 

equals와 hashCode를 모두 overriding 해줘야하는 이유

자바에서는 객체의 동등여부를 판단할 때 equals와 hashCode 메소드를 둘 다 사용하여 비교를 진행한다.

아래 예시를 통하여 확인해보자.

 

Hash방식의 자료구조

자바에서 중복을 허용하지 않는 hash방식의 경우 객체의 중복 여부 판단 시에 hashCode와 Equals 둘 다 사용하여 비교를 진행한다.

Hash 중복 여부 판단 과정

 

따라서 equals와 hashCode를 모두 overriding 해주어야 한다.

 

 

Stream의 distinct 메소드

Stream 내부의 객체를 중복 제거 하는 distinct의 경우 Object.equals를 통하여 판단한다고 쓰여있다.

Stream의distinct의 설명

 

그럼 equals만 overriding 하였을 경우 중복 제거를 해줄까?

 

아래와 같이 테스트 코드를 작성하여 테스트 해보았다.

실행할 테스트 코드

 

실행 결과

 

potatoPizza1과 potatoPizza2가 동일한 값을 가지고 있어 equals가 true였으나 distinct로 중복 제거되지 않았다.

 

 

equals의 API  Note를 보면 아래와 hashCode도 같이 재정의하라고 적혀있다.

equals의 API Note

 

따라서 distinct를 사용하려면 마찬가지로 equals와 hashCode를 모두 overriding하여 동일한 객체로 판단할 수 있게 해주어야 한다. 

 

 

 

 

참고자료

https://mangkyu.tistory.com/101

https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B0%9D%EC%B2%B4%EC%9D%98-hashCode%EB%8A%94-%EA%B3%A0%EC%9C%A0%ED%95%98%EC%A7%80-%EC%95%8A%EB%8B%A4-%E2%9D%8C