ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java - hashCode() & equals()
    Language/Java 2022. 4. 5. 15:34

    hashCode()

    hashCode()란?

    hashCode()는 두 객체가 같은 객체인지 확인한다. hashCode() 메서드는 '=='과 같은 동일 비교 기능을 하며, 반환 값으로 런타임 중 객체의 유일한 정수 값을 반환한다. 일반적으로 Heap에 저장된 객체의 메모리 주소를 반환한다.

     

    해시란?

    해시는 임의의 크기를 가진 데이터(key)를 고정된 크기의 데이터(value)로 변화시켜 저장하는 것이다. key에 대한 해시값을 구하는 과정을 해싱이라고 하며, 이때 사용하는 함수를 해시함수라고 한다.


    equals()

    equals()란?

    equals()는 두 개의 객체가 동일한지 검사하기 위해 사용되는 메서드이다. equals()가 객체를 비교하는 방법은 두 개의 객체가 참조하는 것이 동일한지를 확인하는 것이다. 즉, 두 개의 객체가 가리키는 메모리 주소가 동일할 경우 해당 객체들은 동일한 객체가 되는 것이다.


    hashCode()와 equals()

    hashCode()의 필요성

    동일한 객체는 동일한 메모리 주소를 가져야 하기 때문에, 동일한 객체는 동일한 해시 코드를 가져야 한다는 것은 당연한 사실이다. 따라서, equals() 말고 hashCode()도 같이 재정의하여 동일한 해시 코드를 보장하도록 코드를 구성하는 것이 바람직한 방법이다.

     

    해시 자료 구조
    public class Main {
        public static void main(String[] args) {
            Set<Person> people = new HashSet<>();
    
            people.add(new Person("이순신", 19));
            people.add(new Person("이순신", 19));
    
            System.out.println(people.size());   // 2 출력
        }
    }
    
    class Person {
        private final String name;
    
        private final int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public boolean equals(Object o) {
    
            if (this == o)
                return true;
    
            if (o == null || this.getClass() != o.getClass())
                return false;
    
            Person person = (Person) o;
    
            return Objects.equals(this.name, person.name) && this.age == person.age;
        }
    }

    위 코드에서는 HashSet 자료구조에 동등한 객체 2개를 삽입하였다. 그다음 해당 자료구조의 사이즈를 출력해 보면 2가 나오는 것을 확인할 수 있다. 왜 2가 나오는 것일까?

    그 이유는 바로 해시를 사용한 자료 구조는 key를 결정할 때 hashCode()를 사용하기 때문이다. 즉, 객체가 동일한지 비교하기 전에, 두 객체의 해시 코드가 같은지 비교한 후 두 객체가 동등한 지 판단한다. 이때, hashCode()가 재정의되어 있지 않다면 Object의 hashCode()를 사용하므로 각 객체가 저장된 메모리 주소가 반환된다.

     

    public class Main {
        public static void main(String[] args) {
            Set<Person> people = new HashSet<>();
    
            people.add(new Person("이순신", 19));
            people.add(new Person("이순신", 19));
    
            System.out.println(people.size());   // 1 출력
        }
    }
    
    class Person {
        private final String name;
    
        private final int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @Override
        public boolean equals(Object o) {
    
            if (this == o)
                return true;
    
            if (o == null || getClass() != o.getClass())
                return false;
    
            Person person = (Person) o;
    
            return Objects.equals(this.name, person.name) && this.age == person.age;
        }
    
        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }
    }

    따라서, 해시 자료 구조를 사용하는 경우에는 위 코드와 같이 equals() 외에 hashCode()도 재정의해 주는 것이 좋다.

     

    hashCode()와 equals()를 같이 사용하는 이유

    해시를 사용한 자료구조는 key를 결정할 때 hashCode()를 사용한다. 즉, 객체가 동일한지 비교하기 전에, 두 객체의 해시 코드가 같은지 비교하고 그 후 해당 객체들이 동등한 지 판단한다.

    만약, hashCode()가 재정의되어 있지 않다면 Object의 hashCode()를 사용하기 때문에, 각 객체가 저장된 메모리 주소가 반환된다. 따라서, 해시 자료 구조를 사용하는 경우에는 equals() 외에 hashCode()도 재정의함으로써, 개발자의 재량에 따라 동일성을 비교하는 것이 바람직하다.


    출처

    https://mangkyu.tistory.com/101

    https://steady-coding.tistory.com/604

     

    728x90

    'Language > Java' 카테고리의 다른 글

    Java - Mutex & Semaphore & Monitor  (0) 2022.04.06
    Java - Reflection  (0) 2022.04.05
    Java - Thread  (0) 2022.03.28
    Java - Overloading & Overriding  (0) 2022.03.23
    Java - Checked Exception & Unchecked Exception  (0) 2022.03.22

    댓글

Designed by Tistory.