Qna. equals와 hashcode 메서드를 사용하는 이유
객체의 동등성 비교와 해시 기반 자료구조에서 일관된 동작을 보장하기 위해 equals와 hashcode 메서드를 사용한다.
객체의 동등성 (Equaility)
1. 물리적 동일성
== 연산자를 사용하여 두 객체의 메모리 주소(참조값)가 같은지 비교합니다.
String a = "hello";
String b = "hello";
System.out.println(a == b); // true (String Pool 덕분)
String c = new String("hello");
System.out.println(a == c); // false (다른 객체)
2. 논리적 동일성
equals 메서드를 오버라이딩하여 객체의 내부 상태(멤버 변수)를 비교할 수 있습니다.
기본적으로 equals()는 == 연산자와 동일하게 동작하지만, 오버라이딩 사용할 수 있습니다.
class Person {
String name;
Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return name.equals(person.name);
}
}
- equals()를 오버라이딩하여, 이름이 같은 두 객체를 같은 객체로 취급할 수 있습니다.
hashCode()
- hashCode는 객체를 해시 기반 자료구조(HashMap, HashSet)에 저장하거나 검색할 때 사용합니다.
- 같은 객체라면 항상 같은 해시코드를 반환해야 하며, equlas가 true를 반환하는 두 객체는 반드시 같은 hashcode를 가져야 합니다.
하지만, hashcode가 같다고 해서 equals가 항상 true를 보장하지 않습니다. (해시 충돌이 발생할 수 있음)
@Override
public int hashCode() {
return Objects.hash(name);
}
Hash Collision이란
서로 다른 값이 같은 해시 코드를 가지는 경우를 의미합니다.
hashCode()는 정수 값을 반환하는 함수이며, 서로 다른 객체라도 같은 해시코드를 가질 가능성이 있습니다.
equals()는 객체의 실제 내용을 비교하므로, hashCode() 값이 같아도 내부 값이 다르면 equals()는 false를 반환할 수 있습니다.
hashCode 활용 사례
1. @Cacheable에서 Key 생성 시
Spring의 @Cacheable 어노테이션을 사용하면, Cache Key를 자동으로 생성할 때 hashCOde()가 활용됩니다.
@Service
public class UserService {
@Cacheable("users")
public User getUserById(User user) {
return userRepository.findById(user.getId()).orElseThrow();
}
}
- @Cacheable은 기본적으로 메서드의 파라미터(User user)를 Key로 사용하는데, 이때 객체의 hashCode()를 사용합니다.
class User {
private Long id;
private String name;
@Override
public int hashCode() {
return Objects.hash(id); // ID 기준으로 hashCode 생성
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
User user = (User) obj;
return Objects.equals(id, user.id);
}
}
2. Hibernate (JPA)에서 1차 캐싱
Spring Data JPA를 사용할 때, EntityManager는 1차 캐시를 사용합니다.
- 동일한 트랜잭션 내에서 같은 엔티티를 조회하면, DB가 아닌 캐시에서 가져옵니다.
- 이를 hashCode()와 equals()가 올바르게 구현되지 않으면, 같은 엔티티라도 중복으로 저장될 수 있습니다.
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@Override
public int hashCode() {
return Objects.hash(id); // ID 기반으로 해시코드 생성
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Book book = (Book) obj;
return Objects.equals(id, book.id);
}
}
- 만약 hashCode()를 ID가 아닌 다른 필드 기반으로 만들면,
- findById(1L)를 호출할 때마다 새로운 객체로 간주되어 1차 캐시를 활용하지 못할 수 있습니다.
'JAVA' 카테고리의 다른 글
Java GC 동작 원리: 가비지 컬렉션이 메모리를 정리하는 법 (0) | 2025.04.02 |
---|---|
Java 버전별 변화 및 주요 기능 - java 8, 11, 17, 21 (0) | 2025.03.14 |
Java Stream map vs flatMap 차이점과 활용법 (kotlin) (0) | 2025.03.04 |
Java 21 가상 스레드란? 기존 OS 스레드와의 차이점 정리 (0) | 2025.02.18 |
Java 프로그램 실행 과정, JVM 구조 이해하기 (0) | 2025.02.15 |
Qna. equals와 hashcode 메서드를 사용하는 이유
객체의 동등성 비교와 해시 기반 자료구조에서 일관된 동작을 보장하기 위해 equals와 hashcode 메서드를 사용한다.
객체의 동등성 (Equaility)
1. 물리적 동일성
== 연산자를 사용하여 두 객체의 메모리 주소(참조값)가 같은지 비교합니다.
String a = "hello";
String b = "hello";
System.out.println(a == b); // true (String Pool 덕분)
String c = new String("hello");
System.out.println(a == c); // false (다른 객체)
2. 논리적 동일성
equals 메서드를 오버라이딩하여 객체의 내부 상태(멤버 변수)를 비교할 수 있습니다.
기본적으로 equals()는 == 연산자와 동일하게 동작하지만, 오버라이딩 사용할 수 있습니다.
class Person {
String name;
Person(String name) {
this.name = name;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Person person = (Person) obj;
return name.equals(person.name);
}
}
- equals()를 오버라이딩하여, 이름이 같은 두 객체를 같은 객체로 취급할 수 있습니다.
hashCode()
- hashCode는 객체를 해시 기반 자료구조(HashMap, HashSet)에 저장하거나 검색할 때 사용합니다.
- 같은 객체라면 항상 같은 해시코드를 반환해야 하며, equlas가 true를 반환하는 두 객체는 반드시 같은 hashcode를 가져야 합니다.
하지만, hashcode가 같다고 해서 equals가 항상 true를 보장하지 않습니다. (해시 충돌이 발생할 수 있음)
@Override
public int hashCode() {
return Objects.hash(name);
}
Hash Collision이란
서로 다른 값이 같은 해시 코드를 가지는 경우를 의미합니다.
hashCode()는 정수 값을 반환하는 함수이며, 서로 다른 객체라도 같은 해시코드를 가질 가능성이 있습니다.
equals()는 객체의 실제 내용을 비교하므로, hashCode() 값이 같아도 내부 값이 다르면 equals()는 false를 반환할 수 있습니다.
hashCode 활용 사례
1. @Cacheable에서 Key 생성 시
Spring의 @Cacheable 어노테이션을 사용하면, Cache Key를 자동으로 생성할 때 hashCOde()가 활용됩니다.
@Service
public class UserService {
@Cacheable("users")
public User getUserById(User user) {
return userRepository.findById(user.getId()).orElseThrow();
}
}
- @Cacheable은 기본적으로 메서드의 파라미터(User user)를 Key로 사용하는데, 이때 객체의 hashCode()를 사용합니다.
class User {
private Long id;
private String name;
@Override
public int hashCode() {
return Objects.hash(id); // ID 기준으로 hashCode 생성
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
User user = (User) obj;
return Objects.equals(id, user.id);
}
}
2. Hibernate (JPA)에서 1차 캐싱
Spring Data JPA를 사용할 때, EntityManager는 1차 캐시를 사용합니다.
- 동일한 트랜잭션 내에서 같은 엔티티를 조회하면, DB가 아닌 캐시에서 가져옵니다.
- 이를 hashCode()와 equals()가 올바르게 구현되지 않으면, 같은 엔티티라도 중복으로 저장될 수 있습니다.
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@Override
public int hashCode() {
return Objects.hash(id); // ID 기반으로 해시코드 생성
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Book book = (Book) obj;
return Objects.equals(id, book.id);
}
}
- 만약 hashCode()를 ID가 아닌 다른 필드 기반으로 만들면,
- findById(1L)를 호출할 때마다 새로운 객체로 간주되어 1차 캐시를 활용하지 못할 수 있습니다.
'JAVA' 카테고리의 다른 글
Java GC 동작 원리: 가비지 컬렉션이 메모리를 정리하는 법 (0) | 2025.04.02 |
---|---|
Java 버전별 변화 및 주요 기능 - java 8, 11, 17, 21 (0) | 2025.03.14 |
Java Stream map vs flatMap 차이점과 활용법 (kotlin) (0) | 2025.03.04 |
Java 21 가상 스레드란? 기존 OS 스레드와의 차이점 정리 (0) | 2025.02.18 |
Java 프로그램 실행 과정, JVM 구조 이해하기 (0) | 2025.02.15 |