개발/Java
[JAVA] equals & hashCode
난중후니
2023. 1. 3. 20:25
728x90
반응형
equals()
// Object의 기본 equals 메서드
public boolean equals(Object obj){
return (this == obj);
}
- equals는 두 객체를 비교해 내부 value가 같으면 true, 그렇지 않으면 false를 리턴합니다.
equals() 와 ==의 차이
== : 참조값(객체의 주소값)이 같으니 비교합니다.
equals() : 내부의 값이 같은지 비교합니다.
예시) "abc" 라는 값을 가진 a,b 변수의 비교
String a = "abc";
String b = "abc";
System.out.println("a==b ->>> " + a==b);
System.out.println("a.equals(b) ->>> " + a.equals(b));
결과
a==b ->>> false
a.equals(b) ->>> true
- a==b가 false가 나온 이유는 == 연산자는 a,b의 주소값(참조 값)을 비교하기 때문에 false가 나옵니다. 주소 값은 "abc"라는 값을 저장하기 위한 주소의 값입니다.
- a.equals(b)가 true가 나온 이유는 a와 b의 내부 값인 "abc"가 같은지만 비교하였기 때문입니다.
primitive 타입이 == 비교를 통해 값 비교가 가능한 이유
- primitive(원시타입)는 값이 같다면 주소의 값도 동일하게 저장되기 때문입니다.
- primitive 타입에는 boolean, byte, short, int, long, float, double, char이 있습니다.
hash code
- 객체를 식별하는 하나의 정수 값입니다.
- hashCode() 메소드는 객체의 메모리 주소를 이용해서 해시 값을 추출합니다.
- Collections(HashSet, HashMap, HashTable ...)을 동등한지 비교할 때 사용됩니다.
Collections 비교 과정
- hashCode 메서드의 리턴 값이 일치하는지 확인합니다.
- equals()를 이용하여 내부 값이 일치하는지 확인합니다.
예시
객체에 equals만 재정의 한 경우
일반 객체 비교, List size, HashSet size를 기반으로 비교하였으며
class Book{
String name;
public Book(String name){
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(name, book.name);
}
}
@Test
public void equalsAndHashCodeTest(){
Book book1 = new Book("Java");
Book book2 = new Book("Java");
System.out.println(book1.equals(book2));
List<Book> bookList = new ArrayList<>();
bookList.add(book1);
bookList.add(book2);
System.out.println("bookList Size >>> " + bookList.size());
HashSet<Book> bookHashSet = new HashSet<>();
bookHashSet.add(book1);
bookHashSet.add(book2);
System.out.println("bookHashSet Size >>> " + bookHashSet.size());
}
결과
true
bookList Size >>> 2
bookHashSet Size >>> 2
-> HashSet은 중복을 허용하지 않기 때문에 값이 같은 book1과 book2가 한개로 Set에 등록될 줄 알았지만 Book 객체내에 hashCode 메서드가 재정의 되지 않아서 Object 클래스의 hashCode 메서드가 사용되었습니다. 따라서 book1 과 book2의 hashCode가 다르기 때문에 HashSet에서는 다른 객체로 분리하여 2개가 등록되고 있습니다.
hashCode 재정의
class Book{
String name;
public Book(String name){
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Book book = (Book) o;
return Objects.equals(name, book.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
equals vs hashCode
- equals가 같다면 hashCode는 같습니다.
-> Collections, 객체, primitive 타입에서 비교시에 equals가 성립하려면 값이 같거나 값과 hashCode가 같아야 하기 때문입니다.
- hashCode가 같다고 무조건 equals가 같은건 아닙니다.
-> primitive 타입에서도 hashCode는 사용하지 않지만 값이 같은 경우 equals가 성립하기 때문입니다. 또한 Collections 타입에서도 hashCode가 같아도 내부 값이 다른 경우 equals가 성립하지 않습니다.
728x90
반응형