코딩 하는 가든

Java - 자바 객체 비교하기 (equals / hashcode) 본문

Java

Java - 자바 객체 비교하기 (equals / hashcode)

가든리 2020. 8. 12. 21:59

자바 객체 비교하기 ( equals / hashcode )

자바에서 객체를 비교하는 방법에 대해 기록합니다.

 

Equals 메소드에 대하여

equals의 필요성

아래와 같은 Toy 클래스가 있다고 가정하겠습니다.

그리고 이름은 "자동차" 가격은 10000원을 가진 Toy 객체 두 개를 생성합니다.

 

우리는 장난감의 이름과 가격이 같기 때문에 같은 장난감이라고 판단하고 싶습니다.

우리가 아는 기본적인 비교 방법인 == 비교를 이용해서 두 객체를 비교해 보면 false가 나오게 됩니다.

 

왜냐하면 toy1과 toy2변수는 객체 그 자체가 아닌 객체를 가리키는 레퍼런스를 갖고 있기 때문입니다.

 

따라서 값을 이용해서 객체를 비교하려면 우리는 클래스 안에 equals라는 메소드를 재정의 해야 합니다.

(equals 메소드의 정의 방법에 대해서는 아래 코드의 주석 참고)

 

equals 메소드 재정의 하는 법

이렇게 equals메소드를 재정의 한 후 equals 메소드를 이용해 객체 비교를 하게 되면 아래와 같은 결과를 얻을 수 있습니다.

 

Hashcode에 대하여

우리는 위에서 보았듯 equals 메소드를 이용해 객체를 비교해 보았습니다. 하지만 값이 같은 두 객체를 진정으로 같게 보기 위해서는 hashcode 메소드를 재정의 해야 합니다.

 

hashcode의 필요성

실제로 toy1과 toy2를 그대로 출력해보면 아래와 같은 결과가 나타나게 됩니다.

toy1과 toy2의 레퍼런스 변수를 출력해 보면 '클래스명@알수없는값' 과 같은 결과를 얻게 됩니다. 여기서 @뒤에 붙은 값이 해당 객체의 해쉬값입니다.

 

우리가 자바에서 흔히 사용하는 HashMap, HashSet 등의 자료구조는 내부적으로 객체를 비교할 때 해당 객체의 해쉬값을 사용하여 비교를 합니다. 따라서 toy1과 toy2는 자바 세계에서는 아직 다른 객체로 판별됩니다.

 

우리는 Set이 중복이 없는 데이터의 자료 구조라고 알고 있습니다. 하지만 이러한 Set에 toy1과 toy2를 넣으면 set의 크기는 2가 됩니다. toy1과 toy2의 해쉬값이 다르기 때문에 set은 다른 객체라고 인식했기 때문입니다.

 

따라서 우리는 객체를 이러한 자료구조에서 활용하기 위해 hashcode를 재정의 해야 합니다.

 

hashcode 재정의 하는 방법

우리는 클래스 안에 hashCode 메소드를 오버라이드 하여 멤버 변수를 Objects의 hash메소드의 인자로 넘겨줌으로써 손쉽게 hashcode를 재정의 할 수 있습니다.

 

멤버 변수를 hash 메소드에 넘겨주면 넘어온 변수들에 대해 내부적으로 규칙에 따라 hashcode를 생성해 줍니다.

왜 결과에 31을 곱해주는지는 https://d2.naver.com/helloworld/831311 에 자세하게 나와있습니다.

 

이렇게 해쉬 코드를 재정의 하고 나서 두 레퍼런스 변수인 toy1과 toy2를 출력해보면 같은 해쉬값이 나타나는 결과를 볼 수 있습니다.

 

손쉽게 equals와 hashCode 재정의 하기

방금 보았던 예제는 클래스가 간단하기 때문에 equals와 hashcode를 손쉽게 재정의 할 수 있었습니다. 하지만 객체가 커지고 멤버 변수가 많아진다면 equals와 hashCode를 재정의 할 때 실수가 발생할 수도 있습니다. 따라서 기술의 도움을 받아 손쉽게 두 메소드를 재정의 하는 법을 알아보겠습니다.

 

1. IDE의 도움을 받기

인텔리 제이를 사용한다면 클래스 안에서 커맨드(mac: command + N)를 눌러 equals() and hashCode() 탭을 클릭한다면 인텔리 제이가 빠르고 정확하게 두 메소드를 만들어 주는 것을 볼 수 있습니다.

 

2. 롬복 라이브러리 사용하기

롬복 라이브러리를 사용한다면 클래스 위에 @EqualsAndHashCode 어노테이션을 붙여준다면 롬복 라이브러리가 자동으로 equals와 hashcode를 생성해줄 것입니다.