본문 바로가기
language/java

Java equals()와 hashCode() 완벽 이해하기

by 죄니안죄니 2026. 5. 27.
반응형

Java equals()와 hashCode() 완벽 이해하기

Java를 공부하다 보면 정말 많이 등장하는 메서드가 바로:

 
equals()
hashCode()
 

입니다.

특히:

  • HashMap
  • HashSet
  • 중복 제거
  • 객체 비교
  • JPA Entity
  • Lombok

까지 실무 전체와 깊게 연결됩니다.

초보 시절에는 보통:

equals = 값 비교
hashCode = 해시값
 

정도로 외우고 넘어가기 쉽습니다.

하지만 실제로는:

  • Object 계약(contract)
  • Hash 충돌 처리
  • Collection 내부 구조
  • immutable 설계
  • 성능 문제

까지 전부 연결됩니다.

심지어 실무에서는:

equals/hashCode 잘못 구현
↓
HashMap 조회 실패
↓
장애 발생
 

도 실제로 많이 일어납니다.

이번 글에서는:

  • equals() 의미
  • hashCode() 의미
  • 왜 둘 다 필요한가
  • HashMap 내부 동작
  • Object contract
  • Lombok 주의점
  • 실무 장애 사례

까지 깊게 정리해보겠습니다.


1. 모든 객체는 Object를 상속한다

Java의 모든 클래스는 결국:

 
java.lang.Object
 

상속.

즉 기본적으로:

 
equals()
hashCode()
 

보유.


2. 기본 equals() 동작

Object의 기본 equals는 사실상:

 
==
 

와 거의 동일.

즉:

주소(reference) 비교
 

입니다.


3. 예시

 
User u1 = new User("Kim");
User u2 = new User("Kim");

System.out.println(u1.equals(u2));
 

결과:

false
 

4. 왜 false일까?

현재:

서로 다른 객체
 

이기 때문.

즉:

Heap 주소 다름
 

5. 하지만 우리가 원하는 건?

보통은:

내용 비교
 

원함.

즉:

이름이 같으면 같은 사용자
 

처럼 판단하고 싶음.


6. 그래서 equals 재정의

예:

 
@Override
public boolean equals(Object o) {

    if (this == o) return true;

    if (!(o instanceof User))
        return false;

    User user = (User) o;

    return Objects.equals(name, user.name);
}
객체비교 시 키를 비교하도록 재정의

7. 이제 결과

u1.equals(u2)
 

true
 

가능.


8. hashCode란?

Hash function 기반 개념.

hashCode는:

객체를 정수(int) 값으로 변환한 결과

입니다.


9. 왜 필요할까?

핵심 목적:

빠른 검색
 

입니다.

특히:

  • HashMap
  • HashSet

에서 핵심.


10. HashMap 내부 동작 다시 보기

 
map.put(user, value);
 

실제로:

user.hashCode()
↓
bucket 위치 계산
 

수행.


11. equals만 구현하면 안 되는 이유

매우 중요합니다.

예:

 
equals만 재정의
hashCode 미재정의
 

문제 발생 가능.


12. 실제 문제 예시

 
Set<User> set = new HashSet<>();

set.add(new User("Kim"));

System.out.println(
    set.contains(new User("Kim"))
);
 

13. 기대 결과

true
 

처럼 보임.


14. 그런데 실제론 false 가능

왜냐하면:

hashCode 다름
 

일 수 있기 때문.


15. HashSet 동작 순서

HashSet은 먼저:

hashCode()
 

확인.

그리고 같은 bucket 내부에서:

equals()
 

비교.


16. 즉 둘 다 필요

핵심:

hashCode 먼저
equals 나중
 

객체 전체의 해시값을 확인 후, 객체 내부 키까지 확인


17. Object Contract(계약)

Java는 중요한 규칙 정의.


18. 핵심 규칙

매우 중요.

equals가 true면
hashCode도 반드시 같아야 한다
 

hash(객체A) => 결과123

hash(객체A) => 필연적으로 결과123


19. 반대는 성립 안 함

즉:

hashCode 같다고
equals true일 필요는 없음
 

충돌 가능.

해시는 어떤 크기든 정해진 길이 값으로 치환되기 때문에 중복이 있을 수 있음 


20. 예시

A.hashCode() == B.hashCode()
 

여도:

A.equals(B)
 

는 false 가능.


21. 왜 이런 규칙 필요할까?

HashMap 구조 때문.

같은 객체인데
다른 bucket 저장되면
검색 불가능
 

문제 발생.


22. 올바른 구현 예시

 
@Override
public boolean equals(Object o) {

    if (this == o) return true;

    if (!(o instanceof User))
        return false;

    User user = (User) o;

    return Objects.equals(id, user.id);
}

@Override
public int hashCode() {

    return Objects.hash(id);
}
 

23. 왜 보통 id 기준 비교할까?

실무에서는:

식별자(identity)
 

중심 비교 많음.

예:

  • 회원 ID
  • 주문번호
  • UUID

등.


24. mutable 필드 위험

매우 중요합니다.

예:

 
name 변경 가능
 

인데 hashCode 기반이면?


25. 위험한 상황

 
map.put(user, value);

user.setName("Lee");
 

현재:

hashCode 변경 가능
 

즉:

Map에서 못 찾는 상황
 

발생 가능.


26. 그래서 immutable key 중요(immutable 설계)

HashMap key는 보통:

변하지 않는 값 사용
 

추천.

대표:

  • String
  • UUID
  • Integer

27. String이 안전한 이유

String 은:

immutable
 

입니다.

즉 hashCode 안정적.


28. hashCode 품질도 중요

안 좋은 예:

@Override
public int hashCode() {
    return 1;
}
 

29. 문제

모든 객체 충돌
 

즉:

HashMap 성능 O(N)
 

까지 저하 가능. 성능 문제


30. 좋은 hashCode 특징

핵심:

고르게 분산
 

되는 것.


31. Java Objects.hash()

대표 구현:

 
Objects.hash(id, name)
 

간편하게 hashCode 생성 가능.


32. Lombok @EqualsAndHashCode

Project Lombok 에서 제공.

예:

 
@EqualsAndHashCode
 

33. 장점

자동 생성 가능.

코드 간단.


34. 하지만 실무 주의점

매우 중요.

Entity에 무분별하게 사용 위험 가능.


35. JPA Entity 문제

Jakarta Persistence 환경에서:

Lazy Loading
Proxy
 

와 충돌 가능.


36. 대표 문제

equals 호출 시:

불필요한 DB 조회
 

가능.


37. Entity equals 실무 전략

보통:

PK 기반 비교
 

사용.

하지만 생성 전 ID null 문제도 존재.

매우 조심 필요.


38. Set에서 equals/hashCode 중요

HashSet은:

중복 제거 기준
 

으로 equals/hashCode 사용.


39. Collection 전체와 연결

대표 사용처:

컬렉션 사용
HashMap key 비교
HashSet 중복 제거
ConcurrentHashMap key 비교

40. == 와 equals 차이

매우 중요.

비교 의미
== 주소 비교
equals 논리 비교

41. String 비교 실수

안 좋은 예:

if (a == b)
 

보통은:

a.equals(b)
 

사용.


42. 실무에서 자주 하는 실수

1) equals만 구현

HashMap 동작 이상 가능.

2) mutable 필드 사용

Map 검색 실패 가능.

3) == 로 문자열 비교

매우 흔한 실수.

4) Lombok 무지성 사용

JPA Entity 문제 가능.


43. 핵심 흐름 요약

hashCode()
↓
bucket 위치 결정
↓
equals()
↓
진짜 동일 객체 판별
 

44. 가장 중요한 핵심 한 줄

equals는 “논리적 동일성”,
hashCode는 “빠른 검색 위치 계산”을 위한 것이다
 

입니다.


45. 정리

equals()와 hashCode()는 단순 메서드가 아닙니다.

실제로는:

  • HashMap 내부 구조
  • Hash 충돌 처리
  • Collection 성능
  • 객체 동일성
  • JPA Entity 설계

전체와 연결되는 Java 핵심 개념입니다.

특히 실무에서는:

  • Object Contract
  • immutable key
  • equals/hashCode 재정의
  • Lombok 주의점
  • HashMap 동작 원리

를 정확히 이해하는 것이 매우 중요합니다.

다음 글에서는:

Comparable vs Comparator

를 정렬 전략, TreeMap/TreeSet 내부 동작, 람다 기반 정렬까지 포함해서 깊게 정리해보겠습니다.

반응형

댓글