자바의 HashMap 구현체를 사용하면서 배열이나 사용자 정의 값을 키로 가지는 경우 사용하는 방법을 정리한 글입니다.
자주 쓰이는 정수값이나 문자열은 단순히 get()
을 통해서 값을 얻어올 수 있지만, 그렇지 않은 경우에는 추가적인 작업이 필요합니다.
HashMap에서 key의 entry 찾기
자바 HashMap 클래스는 hashCode()
와 equals() || ==
을 이용하여 key에 해당하는 entry를 찾습니다. 구체적으로 k라는 키를 찾는다고 할 때 다음의 단계를 거칩니다.
k.hashCode()
를 통해 해당 entry가 담긴 버킷을 탐색- 얻은 버킷의 entry 키가 k1이라고 할 때,
k==k1 || k.equals(k1)
이면 k1 entry를 리턴
배열이나 직접 구현한 객체를 키로 사용하는 경우 같은 내용이 담긴 두 개의 객체가 있다고 하더라도 hashCode를 통해 다른 버킷에 저장되어 원하는 결과가 나오지 않게 됩니다. 게다가 같은 버킷을 공유한다고 하더라도, equals
함수는 기본값으로 ==
을 통해 비교하므로 같은 entry를 리턴하지 않습니다. 그래서 hashCode
함수와 equals
에 대한 재정의를 하여 HashMap 사용이 가능하게 됩니다.
1. hashCode() 구현하기
* hashing 에 대해 깊게 조사한게 아니라서 제가 사용한 방법 위주로 작성해두었습니다.
Objects.hash() - JAVA 7
보통 객체를 키로 사용할 때는 멤버변수가 여러개이고, 각 변수들의 값이 모두 일치하는 객체를 동일하다고 판단합니다.Pair
클래스 내 변수가 y
, x
로 주어졌을 때 해시 함수는 다음과 같습니다.
private class Pair {
int y;
int x;
public Pair(int y, int x) {
this.y = y;
this.x = x;
}
@Override
public int hashCode() {
return Objects.hash(y, x);
}
}
Objects.hashCode() - JAVA 7
Ojbect의 hashCode와 다른 점은 nullsafe하다는 점입니다. Objects.hashCode(null)
인 경우 0을 리턴합니다.
Object.hashCode()
이 경우는 nullsafe하지 않아 null을 해싱하려고 하는 경우 NullPointerException
이 발생합니다.
2. equals() 구현하기
equals함수는 객체가 일치해야하는 조건으로 재정의하면 됩니다.
@Override
public boolean equals(Object obj) {
return (this.y == ((Pair)obj).y) && (this.x == ((Pair)obj).x);
전체 예시
private class Pair {
int y;
int x;
public Pair(int y, int x) {
this.y = y;
this.x = x;
}
@Override
public int hashCode() {
return Objects.hash(y, x);
}
@Override
public boolean equals(Object obj) {
return (this.y == ((Pair)obj).y) && (this.x == ((Pair)obj).x);
}
'Java&Kotlin' 카테고리의 다른 글
[Kotlin] Collection 의 크기가 작은 경우 Sequence 가 성능이 더 떨어질 수 있는 이유 (0) | 2022.10.10 |
---|---|
[Kotlin] 제네릭스 (0) | 2022.05.21 |
[Kotlin] 클래스와 인터페이스 (0) | 2022.04.27 |
[JAVA] 제너릭 타입으로 배열을 만들 수 없는 이유 (타입 추론) (0) | 2022.03.09 |