hashCode / equals 메소드

Dayeon myeong·2022년 3월 2일
1

면접

목록 보기
5/35

hashCode / equals 메소드의 역할에 대해 아시는 내용을 최대한 설명해주세요.

HashMap, HashSet의 경우 내부적으로 객체의 해시코드를 구해서 해시 버킷에 저장한다. 또한 get 조회시에도 hashCode와 Equals를 통해 객체를 찾는다. 만약 논리적으로 동일한 두 객체에 대해서 equals와 hashCode를 정의해주어야 HashSet, HashMap에 중복없이 객체가 하나만 저장된다.

equals는 객체의 멤버들이 일치하는지, String이나 Integer같은 값타입에 대해서 값 자체가 일치하는지와 같이 내용을 비교할 때 쓰인다. 또한 컬렉션 프레임워크에서 equasl를 활용해서 contains 메서드로 객체를 조회한다.

상속을 통해 새로운 필드를 추가한 자식클래스가 있을 경우 equals를 재정의하는 것이 굉장히 까다롭다. 대칭성, 추이성, 리스코프 치환, 중요 필드 무시 같은 문제가 생겨서 상속 대신 컴포지션 방식을 통해 equals를 재정의할 수 있다.

또한, hashCode는 성능에도 중요한 요소이다. 따라서 아무렇게나 재정의해도 안된다.

//사용금지
@Override
	public int hashCode() {
		return 42;
	}

위코드는 모든 객체에서 똑같은 해시 코드를 내어주므로 모든 객체가 해시 테이블의 버킷 하나에 마치 연결리스트linked list처럼 동작한다. 그 결과 평균 수행 시간이 O(1)인 해시 테이블이 O(n)으로 느려져서, 객체가 많아지면 도저히 쓸 수 없게 된다.

따라서 좋은 해시함수라면 논리적으로 같지 않은 서로 다른 인스턴스에 대해 다른 해시코드를 반환해야 한다. 논리적으로 동일한 관계인 객체들만 해시코드가 같아야 한다.

또한 해시 코드를 계산할 때도 핵심 필드를 무시해선 안된다. 어떤 경우에는 핵심 필드가 인스턴스들의 해시 코드를 넓은 범위로 고루 퍼뜨려주는 효과를 주는 경우도 있다. 만약 이런 필드를 생략해버리면, 단 몇개의 해시코드로 집중되어서 특정 버킷에만 데이터가 쌓인다. 따라서 해시 테이블의 속도에 영향을 준다.

아래 참고
아이템 11 equals를 재정의하려거든 hashCode도 재정의하라

profile
부족함을 당당히 마주하는 용기

0개의 댓글