자바에서 모든 객체들이 기본적으로 상속받는 Object 클래스에 기본적으로 equals와 hashCode 메소드가 존재한다.
equals 메소드
두 개의 객체가 동일한지 비교하는데 쓰이는 메소드이다.
기본적으로 두 객체의 주소값이 동일할 경우 true를 return한다.
보통 equals 메소드를 오버라이드 후 객체 내부의 값을 비교하여 동일 여부를 판단하곤 한다.
hashCode 메소드
객체가 저장되어 있는 주소값을 기준으로 hashCode를 생성하여 return 한다.
어플리케이션이 실행되는 동안 하나의 객체는 항상 동일한 hashCode값을 return한다.
hashCode native 메소드로 경우 자바가 아닌 C, C++ 같은 네이티브 언어로 작성된 메소드이다.
자바 프로그램에서는 JNI(Java Native Interface)를 통해 호출하여 사용한다.
허나 hashCode값이 동일하다해서 주소값이 동일한 것은 아니다.
오버라이딩
우리는 객체를 비교할 때 편리하기 하기 위하여 equals와 hashCode 메소드를 오버라이딩하여 사용할 수 있다.
Lombok을 사용할 경우 @EqualsAndHashCode를 사용하여 편리하게 오버라이딩 할 수 있다.
(Lombok을 사용하지 않을 경우 IDE에서 기본적으로 제공해주는 생성 기능을 사용하면 된다)
@EqualsAndHashCode을 사용한 결과를 디컴파일해보면 아래와 같다.
Overriding 된 equals 메소드
객체의 주소값만 비교하던 기존과 달리 객체 내부의 값이 같을 경우에도 true를 return 해준다.
Overriding 된 hashCode메소드
hashCode 생성 시 객체에 저장되어 있는 값을 기반으로 생성하여 값이 동일할 경우 hashCode값이 동일하게 나온다.
참고 - String의 경우 기본적으로 equals와 hashCode가 오버라이딩 되어있다.
equals와 hashCode를 모두 overriding 해줘야하는 이유
자바에서는 객체의 동등여부를 판단할 때 equals와 hashCode 메소드를 둘 다 사용하여 비교를 진행한다.
아래 예시를 통하여 확인해보자.
Hash방식의 자료구조
자바에서 중복을 허용하지 않는 hash방식의 경우 객체의 중복 여부 판단 시에 hashCode와 Equals 둘 다 사용하여 비교를 진행한다.
따라서 equals와 hashCode를 모두 overriding 해주어야 한다.
Stream의 distinct 메소드
Stream 내부의 객체를 중복 제거 하는 distinct의 경우 Object.equals를 통하여 판단한다고 쓰여있다.
그럼 equals만 overriding 하였을 경우 중복 제거를 해줄까?
아래와 같이 테스트 코드를 작성하여 테스트 해보았다.
potatoPizza1과 potatoPizza2가 동일한 값을 가지고 있어 equals가 true였으나 distinct로 중복 제거되지 않았다.
equals의 API Note를 보면 아래와 hashCode도 같이 재정의하라고 적혀있다.
따라서 distinct를 사용하려면 마찬가지로 equals와 hashCode를 모두 overriding하여 동일한 객체로 판단할 수 있게 해주어야 한다.
참고자료
'BackEnd > Java' 카테고리의 다른 글
DTO 그렇게 쓰는 거 아닌데 ㅋㅋ (0) | 2024.03.17 |
---|---|
Java HashMap이 List보다 contains의 성능이 더 좋은 이유 (2) | 2023.11.26 |
JAVA 객체 배열, 리스트 값 비교(Comparable, Comparator)를 통한 정렬 (0) | 2023.09.03 |
JAVA에 Call by refernce는 없다. (0) | 2023.07.03 |
JAVA finalize() 소멸자 메소드에 대해 (0) | 2023.05.14 |