[JAVA] equals & hashCode

배세훈·2023년 1월 3일
0

java

목록 보기
16/16

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 비교 과정

  1. hashCode 메서드의 리턴 값이 일치하는지 확인합니다.
  2. 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

  1. equals가 같다면 hashCode는 같습니다.
    -> Collections, 객체, primitive 타입에서 비교시에 equals가 성립하려면 값이 같거나 값과 hashCode가 같아야 하기 때문입니다.

  2. hashCode가 같다고 무조건 equals가 같은건 아닙니다.
    -> primitive 타입에서도 hashCode는 사용하지 않지만 값이 같은 경우 equals가 성립하기 때문입니다. 또한 Collections 타입에서도 hashCode가 같아도 내부 값이 다른 경우 equals가 성립하지 않습니다.

profile
성장형 인간

0개의 댓글