발단
과제를 진행하는 중 아래와 같은 코드를 작성했다.
public class Email { private final String address; public Email(String address) { Assert.notNull(address, "주소는 null이 될 수 없습니다."); Assert.isTrue(address.length() >= 4 && address.length() <= 50, "주소는 5자리에서 50자리 사이여야 합니다."); Assert.isTrue(checkAddress(address), "유효하지 않은 이메일 주소입니다."); this.address = address; } private static boolean checkAddress(String address) { return Pattern.matches("\\b[\\w\\.-]+@[\\w\\.-]+\\.\\w{2,4}\\b", address); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Email email = (Email) o; return address.equals(email.address); } @Override public int hashCode() { return Objects.hash(address); } public String getAddress() { return address; } }
equals 메서드를 재정의(Override)하는 이유는 해당 클래스의 객체들을 비교 할 때 참조변수(메모리주소)를 비교하는 것이 아닌 필드 값들이 일치하는지 확인하기 위해 작성했다.
하지만, hashcode는?
Intellij에서 같이 재정의 하래요.

정말이다. 단축키를 통해 orverride를 하려하면 equals()와 hashCode()를 같이 override하게 한다.
진짜 이유는 HashMap에 있다.
HashMap은 key값을 기준으로 해시 함수를 이용하여 고유한 식별 값인 해시 값을 만든다.
이때, hashCode가 해시 값을 만드는 역할을 한다.
HashMap에서 put이나 get을 할 때, HashMap에 같은 객체가 존재하는지 확인하기 위해 equals를 사용해 비교한다.
실습 코드는 아래와 같다.
같은 key지만 value는 서로 다르게 하여 put을 한다. map의 size가 1인지 확인 후 get을 하여 값이 바뀌었는지 확인 한다.
@Test @DisplayName("값은 값을 가진 Email 객체는 HashMap의 Key값도 같다.") void checkHashMapKeySame() { Email email = new Email("nnagman@kakao.com"); Map<Email, String> hs = new HashMap<>(); System.out.println("put first Email"); hs.put(email, email.getAddress()); System.out.println("put second Email"); hs.put(new Email("nnagman@kakao.com"), "hi"); System.out.println("put third Email"); hs.put(new Email("nnagman@kakao.com"), "test"); assertThat(hs.size(), is(1)); System.out.println("get value by key of map"); assertThat(hs.get(email), is("test")); }
put first Email hashcode() called - computed hashcode: 597981801 put second Email hashcode() called - computed hashcode: 597981801 equals() called put third Email hashcode() called - computed hashcode: 597981801 equals() called get value by key of map hashcode() called - computed hashcode: 597981801
실행 후 콘솔 출력은 위와 같다. 예상 했던 대로 hashcode를 생성하고 equlas를 호출하여 같은 key가 있는지 확인한다.
결론
만약 equals()를 재정의하지 않았다면 hashcode로 위치는 찾을 수 있겠지만 같은 객체인지 값을 비교 할 수 없다.
그리고 hashCode()만 재정의한다면 같은 값을 가진 객체라도 해시값은 달라질 것이다.
그러니 equals()를 재정의하여 객체를 비교하는 방법을 바꿨다면 hashCode()도 재정의하여 HashMap과 같은 녀석을 사용할 때, 문제가 일어나지 않도록 해야 한다.
참고
+)
제 이펙티브 자바 스터디에서 [2기-P]이용훈 님께서 작성해주셨던 자료입니다!
