JAVA-기초/JAVA기본

[Java] hashCode와 Equals를 함께 재정의하는 이유

공부하고 기억하는 공간 2024. 3. 17. 23:33
728x90
반응형
SMALL

 

Set과 Map의 타입이 Wrapper Class가 아닌 Object를 받을 때 중복 검사는 어떻게 진행하는가?

➕ hashCode() 메서드를 오버라이딩하여 리턴된 해시코드 값이 같은지 판단합니다. 값이 다르다면 다른 객체로 판단하고, 해시코드 값이 같다면 equals()메서드를 오버라이딩 하여 다시 비교합니다.

위의 개념을 위해서는 동일성과 동등성을 먼저 알아야한다.

 

**동일성** : 두 개의 객체가 완전히 하나의 같은 객체인지 판단하는 것. 즉 , 메모리에 저장된 주소공간이 완전히 같을 경우 동일성이 보장된다.

 

 

**동등성** : 두 객체의 주소공간이 달라도 단순히 가지고 있는 값만 같다면 동등성이 보장된다.

 

이는 단순 문자열(원시형)과 객체로 생성한 값 사이의 차이점과 동일하다.

그 다음으로는 equals의 필요성이다. equals가 필요한 이유는 객체지향의 캡슐화 개념때문이기도 하다. 내부 사앹 정보를 숨긴 채로 두 객체의 동등성 정보를 파악해야 하는데, 따라서 상태 간 비교가 아닌 더 큰 개념에서 객체와 객체 사이의 정보를 비교해야 한다. 그러므로 equals의 오버라이딩이 필요하다.

  • 예시코드(equals 그대로 사용)
    • 내부 상태가 완전히 같아도 동등성을 보장할 수 없다.
    public static void main(String[] args) {
            Car car1 = new Car(1,"sonata");
            Car car2 = new Car(1,"sonata");
            System.out.println(car1.equals(car2)); //false
        }
    
  • 예시코드(equals를 재정의)
    • 동등성이 보장된다.
    public class Car {
    
        private final int id;
        private final String name;
    
        public Car(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
    
            Car car = (Car) o;
    
            if (id != car.id) {
                return false;
            }
            return Objects.equals(name, car.name);
        }
    }
    
    public static void main(String[] args) {
            Car car1 = new Car(1,"sonata");
            Car car2 = new Car(1,"sonata");
            System.out.println(car1.equals(car2)); //true
        }
    

마지막으로 가장 중요한 hashcode는 왜 필요한가이다. equals만 잘 재정의하면 모든 객체의 동등성이 보장될 것 같지만 그렇지 않다. Hash값을 사용하는 Hash Collection 자료구조(HashMap, HashSet, HashTable)때문에 발생한다.

  • 예시코드
    • Set을 사용하여 완전히 상태가 같은 객체를 두 번 넣어지만 길이가 1이아닌 2가 나온다.
    • 동등성 보장에 실패한 것이다.
    • 원인은 아래의 사진과 같다.
    public static void main(String[] args) {
            Set<Car> cars = new HashSet<>();
            cars.add(new Car(1, "sonata"));
            cars.add(new Car(1, "sonata"));
    
            System.out.println(cars.size()); // 2 -> HashSet 사이즈가 1이 아닌 2임 
        }
    

보장되지 않는 이유

  • Hash를 사용하는 Collection들은 객체의 동등성 비교를 다음 고정과 같이 수행한다.
  • 일단 hashcode값이 서로 같아야만 equals메소드로 객체비교를 수행한다.
  • hashcode와 equals를 모두 재정의 해줘야 객체의 동등성이 비교된다.

 

728x90
반응형
SMALL