[JAVA] hashCode

may_yun·2023년 4월 19일
0

JAVA

목록 보기
9/12
post-thumbnail

hashCode란?

객체를 식별하기 위해서 해시 알고리즘에 의해 생성된 정수값
엄말히 말하면 해시코드는 주소값은 아니고, 주소값으로 만든 고유한 숫자값

  • Object의 Hashcode() 메소드는 객체의 메모리 번지(객체의 주소 값)를 이용해서 해시 코드를 만들어 리턴하기 떄문에 객체 마다 다른 값을 가지고 있다.
  • ⭐️ 이때, 객체의 값을 동등성 비교시 hashCode()를 오버라이딩(재정의)할 필요성이 있다.

객체 동등성 비교

  • 1) HashCode() 비교: 객체 인스턴스마다 각기 다른 주해시코드를 가지고 있다
    • 메소드를 실행해서 리턴된 해시코드 값이 같으면 동일한 객체로 판단하고 equals() 메소드로 2차 비교, 다르면 다른 객체로 판단한다
public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("홍길동");
        Person p2 = new Person("홍길동");

        // 객체 인스턴스마다 각기 다른 주해시코드(주소))를 가지고 있다.
        System.out.println(p1.hashCode()); // 622488023
        System.out.println(p2.hashCode()); // 1933863327
    }
}
  • 2) equals() 비교: 객체 내부의 값 비교
    • hashcode() 값이 같으면 equals()로 다시 비교한다. 이 두개가 모두 맞아야 동등 객체로 판단하는 것. 즉 해시코드 값이 다른 엔트리까지를 동치성 비교를 시도조차 하지 않는다

위 그림에서 세객체는 서로 같은 해시값을 갖는다
따라서 hashcode() 메서드는 같은 값을 리턴하지만, 서로 값이 다른 객체이기 때문에 equals() 메서드는 false 리턴

hashcode를 이해하기 위해서는 HashTable 작동 원리를 먼저 이해하자

HashTable 뿐만 아니라 HashMap, HashSet 모두 동작 원리가 동일하다

  • HashTable은 <key, value> 형태로 데이터를 저장
    • key: 해시 함수(Hash Function)을 이용해서 key 값을 기준으로 고유한 식별값인 해시값을 만든다. (해시코드가 해시값을 만드는 역할을 함) 이 해시값을 버킷(Bucket)에 저장한다.
      ⭐️해시 충돌(Hash Collisions): hashTable의 크기는 한정적이기 때문에 서로 다른 객체라 하더라도 같은 해시값을 갖게 될 수도 있다.
  • 해시 충돌이 발생할 경우
    • 해당 버킷(Bucket)에 LinkedList 형태로 객체를 추가한다
    • java8 이상부터 LinkedList 아이템 갯수가 8개 이상으로 넘어가면 TreeMap 자료구조로 저장된다.

이처럼 같은 해시값의 버킷 안에 다른 객체가 있는 경우 equals 메서드가 사용되는 것

  • HashTable에 객체를 추가하는 경우
    • 값이 같은 객체가 이미 있다면 equals()는 true: 기존 객체를 덮어쓴다
    • 객체가 없다면 equals() false: entry를 LinkedList에 추가
  • HashTable에 객체를 조회하는 경우
    • 값이 같은 객체가 있다면 그 객체를 리턴
    • 없다면 null을 리턴

equals와 hashcode는 왜 같이 재정의 해야하는가?

EqualsAndHashCode를 사용하는 이유

만약 equals()와 hashCode()중 하나만 재정의 하면,

  • hashcode()를 재정의 하지 않으면 같은 값 객체라도 해시값이 다를 수 있다.
    따라서 HashTable에서 해당 객체가 저장된 버킷을 찾을 수 없다
  • equals()를 재정의 하지 않으면 hashcode()가 만든 해시값을 이용해 객체가 저장된 버킷을 찾을 수는 있지만 해당 객체가 자신과 같은 객체인지 값을 비교할 수 없기 떄문에 null을 리턴하게 된다. 따라서 이 역시 원하는 객체를 찾을 수 없다

이러한 이유로 객체의 정확한 동등 비교를 위해서는 특히 Hash 관련 컬렉션 프레임워크를 사용할 때는 Object의 equals() 메소드만 재정의하지 말고 hashcode()메소드도 재정의해서 논리적 동등 객체일 경우 동일한 해시코드가 리턴되도록 해야한다.


참고

profile
개발 일지

0개의 댓글