이전에 equals에 대해 알아봤다. equals와 짝꿍인 hashCode를 알아보자.
종류과 숫자를 맴버 변수로 갖는 카드 클래스가 있다. equals는 구현해 뒀다.
class Card {
private String kind;
private int number;
@Override
public boolean equals(Object o) {
// 종류와 숫자가 같다면 true
}
}
같은 값을 갖는 객체를 2개 만들었다.
중복 허용하지 않는 HashSet에 Card 객체를 넣었다. 두 객체의 값이 같고 equals 메서드도 구현해뒀기 때문에 set의 size는 1로 예상할 수 있다.
확인해보니 2개의 객체가 그대로 들어있다. 제대로 중복 제거가 되지 않았다. 왜 그럴까?
*public* static void main(String[] args) {
Card card1 = new Card("spade", 1);
Card card2 = new Card("spade", 1);
HashSet<Card> cards = new HashSet<>();
cards.add(card1);
cards.add(card2);
System.out.println(cards.size()); // 2
}
해싱기법을 사용하는 자료구조 (HashMap, HashSet 등)는 객체를 해시코드로 변환해서 같은 객체인지 판단한다.
더 알아보기 : 해시테이블
중복제거가 되지 않는 이유는 두 객체의 해시코드가 다르기 때문이라고 생각할 수 있다.
객체들의 해시코드 찍어본다.
System.out.println(card1.hashCode()); // 883049899
System.out.println(card2.hashCode()); // 664223387
// 주소 값으로 해시코드를 생성하기 때문에 값이 다르다.
맞았다. 두 값이 다르다. 어떻게 해결할까?
해시코드를 오버라이드 해서 주소가 다르더라도 값이 같다면 두 객체를 같은 객체로 판단하게 만들어야 한다.
Objects.hash(Object… values)
를 사용한다. 종류와 숫자를 조합해서 해시코드를 생성한다.
@Override
public int hashCode() {
return Objects.hash(kind, number);
}
결과 확인
System.out.println(card1.hashCode()); // -896190659
System.out.println(card2.hashCode()); // -896190659
System.out.println(cards.size()); // 1
// hashCode() 오버라이드 후 결과 확인
성공!
- HasehMap이나 HashSet을 사용할 때는 꼭 equals, hashCode를 재정의하자!
- equals() 오버라이드할 때 hashCode()도 오버라이드 하자.