HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🚀
Random Bit Flip
/
🐧
[2기 - 타일러] 8주차 RBF
/
🌇
Object의 메서드인 equals와 hashCode (1)
🌇

Object의 메서드인 equals와 hashCode (1)

발단

과제를 진행하는 중 아래와 같은 코드를 작성했다.
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에서 같이 재정의 하래요.

notion image
정말이다. 단축키를 통해 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과 같은 녀석을 사용할 때, 문제가 일어나지 않도록 해야 한다.
 

참고

https://jisooo.tistory.com/entry/java-hashcode와-equals-메서드는-언제-사용하고-왜-사용할까
https://woodcock.tistory.com/24
+) 수미 김 제 이펙티브 자바 스터디에서 [2기-P]이용훈 님께서 작성해주셨던 자료입니다!
Effective-Java/Item11_equals를_재정의하려거든_hashCode도_재정의하라.md at main · YHLEE9753/Effective-Java
2022/04/08 equals 를 재정의한 클래스 모두에서 hashCode도 재정의해야 한다. 그렇지 않는다면 hashCode 일반 규약을 어기게 되어 해당 클래스의 인스턴스를 HashMap이나 HashSet 같은 컬렉션의 원소로 사용할 때 문제를 일으킬 것이다. equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다.
Effective-Java/Item11_equals를_재정의하려거든_hashCode도_재정의하라.md at main · YHLEE9753/Effective-Java
https://github.com/YHLEE9753/Effective-Java/blob/main/app/src/main/java/com/programmers/java/chapt3/item11/Item11_equals%EB%A5%BC_%EC%9E%AC%EC%A0%95%EC%9D%98%ED%95%98%EB%A0%A4%EA%B1%B0%EB%93%A0_hashCode%EB%8F%84_%EC%9E%AC%EC%A0%95%EC%9D%98%ED%95%98%EB%9D%BC.md
Effective-Java/Item11_equals를_재정의하려거든_hashCode도_재정의하라.md at main · YHLEE9753/Effective-Java