왜 equals
재정의 후 hashCode
를 재정의해야 하는가?
- 그 이유는 논리적으로 같은 객체는 같은 해시코드를 반환해야하기 때문!
- Hash 함수를 사용하는 컬렉션을 사용하지 않으면 hashCode를 재정의하지 않더라도 문제가 발생하지 않는다. 하지만 애플리케이션 레벨에서 바라봤을 때 해시 컬렉션을 사용하지 않는다고 확신하기 어렵다. 따라서 hashCode도 같이 재정의 하는 것이 필요하다.
equals만 재정의 한 경우
import java.util.*;
public class Car {
private final String name;
public Car(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o)return true;
if (o == null || getClass() != o.getClass()) return false;
Car car = (Car) o;
return Objects.equals(name, car.name);
}
}
class Car Test {
public static void main(String[] args) {
Car carA =new Car("sasca");
Car carB =new Car("sasca");
System.out.println(carA.equals(carB));// true
List<Car> carList =new ArrayList<>();
carList.add(new Car("sasca"));
carList.add(new Car("sasca"));
System.out.println(carList.size());// 2Set<Car> carSet =new HashSet<>();
carSet.add(new Car("sasca"));
carSet.add(new Car("sasca"));
System.out.println(carSet.size());//2 (문제 발생)
}
}
equals
만 재정의한 경우 두 객체는 논리적으로 같은 객체로 판단되며 equals는 true의 결과 값을 갖게 된다. 당연히 List
타입의 컬렉션에 두 객체를 넣으면 정상 동작한다.
Set
타입의 중복되지 않는 객체를 넣을 때 문제가 발생한다. 1이 나와야하지만, 예상과 다르게 2가 나온다. 그 이유는 hash
값을 사용하는 컬렉션을 사용할 때 문제가 발생하기 때문이다.
hash Collection 동작 과정

- 컬렉션의
HashMap
, HashSet
, HashTable
은 객체가 논리적으로 같은지 비교할 때 다음과 같은 과정을 거친다.
System.out.println(carA.hashCode());// 2109957412
System.out.println(carB.hashCode());// 901506536
- 두 객체의 Object 클래스의 hashCode를 출력해보면 다르다는 것을 볼 수 있다. 즉, hashCode가 다르기 때문에 equals 비교를 하기 전에 다른 객체로 판단이 된다.
hashCode도 같이 재정의한 경우
@Override
public int hashCode() {
// return Objects.hash(name); JAVA 7return name.hashCode();
}
System.out.println(carA.hashCode());// 109208323
System.out.println(carB.hashCode());// 109208323
Set<Car> carSet =new HashSet<>();
carSet.add(new Car("sasca"));
carSet.add(new Car("sasca"));
System.out.println(carSet.size());// 1 정상 동작
hashCode
를 재정의 해줌으로 같은 해시 코드 값을 반환하게 되었다. 따라서 해시 컬렉션에서 equals를 비교할 수 있게 되고 동등 객체로 판단이 된다.
- 자바 7버전 부터 사용 가능한
Objects.hash()
유틸리티 메서드, 롬복의 @EqualsAndHashCode
를 통해 편리한 해싱을 적용할 수 있다.