해시 함수(Hash Function)
를 말한다.해시 값(Hash Value)
또는 해시 코드(Hash Code)
라고 불린다.해시 함수는 다음과 같은 특성을 가져야 한다.
데이터 검색 및 저장: 해시 테이블(Hash Table)
과 같은 자료구조에서 빠른 데이터 검색을 위해 사용된다.
데이터 무결성 검증: 파일이나 메시지의 변경 여부를 확인하기 위해 해시 값을 비교한다.
암호화 및 보안: 비밀번호 저장, 디지털 서명, 인증 등에 사용되는 암호화 해시 알고리즘이 있다.
데이터 분산 및 로드 밸런싱: 대규모 시스템에서 데이터를 효율적으로 분산시키기 위해 활용된다.
자바는 해시 알고리즘을 다양한 형태로 제공하며, 주로 다음 두 가지 영역에서 사용된다.
hashCode()
메서드와 해시 기반 컬렉션Object
클래스로부터 hashCode()
메서드를 상속받는다.HashMap
, HashSet
, Hashtable
등)에서 객체를 빠르게 저장하고 검색하는 데 사용된다.사용자 정의 클래스에서 hashCode()
를 오버라이딩할 때는 equals()
메서드와의 일관성을 유지해야 한다.
즉, 두 객체가 equals()
로 동일하다고 판단되면, 두 객체의 hashCode()
도 동일해야 한다는 소리이다.
public class User {
private String id;
public User(String id) {
this.id = id;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id);
}
@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
위의 예제는 id
를 기반으로 체크하고 있음
HashSet
에 값을 저장할때 인덱스로 사용할 수 있도록 원래의 값을 계산한 인덱스를 해시 인덱스라 한다.
주의
이해하기 쉽게 설명한것이며 실제 자바의 해시 인덱스 계산 방식은 다릅니다.
private int hashIndex() {
// Objects.hashCode() 는 음수 값을 가질 수 있어서 절댓값을 사용했음
return Math.abs(Objects.hashCode()) % 배열의 크기;
}
요약
해시 코드: 데이터를 대표하는 값
해시 함수: 해시 코드를 생성해주는 함수
해시 인덱스: 해시 코드를 사용해서 데이터의 저장 위치를 결정하는 값
위의 해시 인덱스에서 배열에 값을 저장할때 해시 인덱스를 통해 저장한다고 했다.
그리고 다른 데이터여도 같은 해시 코드가 나올 수 있다고 했다.
이 해시 코드를 배열의 크기로 나머지 연산을 하면 똑같은 해시 인덱스가 나오는데 이 때 같은 인덱스에 값을 저장하는 것을 해시 충돌이라고 한다.
arr = [null, 1, null, 3, 4, null, null, null, null, [9, 99]];
실제 HashSet 은 위처럼 데이터 저장이 되지 않습니다. 예시입니다.
위를 보면 배열의 크기는 10
이고 값으로는 9
, 99
를 입력했더니 같은 인덱스인 9
에 값이 두 개가 저장된 것이 보인다.
HashSet
을 예시로 처음에는 1차원 배열 상태로 값을 저장하다가 해시 충돌이 나는 경우에는 내부에 LinkedList
를 새로 생성하여 값을 위처럼 저장하게 된다.
이 때 해당 인덱스의 값을 조회할때는 O(n)
의 성능이 나온다.
만약 해당 인덱스에 값이 8개 이상이 저장되는 경우에는 LinkedList
에서 레드-블랙 트리
로 전환되어 검색 기능을 O(log n)
으로 최적화 한다.