hash란?
- 임의의 길이를 갖는 데이터를 고정된 길이의 데이터로 변환(매핑)하는 것
- abcd 라는 문자열이 있다면 이를 특정 길이(ex 256bit, 512bit...)의 데이터로 변환시킨다는 것 (Hashing 이라고 함)
- 해시함수를 돌리기 전 문자열의 길이가 얼마건 일정한 길이를 얻는다.
- 변환한 데이터를 다이제스트 라고 한다.
hash를 사용하는 이유?
- 특정 값에 대한 다이제스트는 변하지 않기 때문에 이 다이제스트의 값을 배열의 위치(index)로 활용 (검색 속도 빠름)
- 동일한 메세지(값)에 대해서는 동일한 다이제스트를 갖기 때문에 중복을 허용하지 않는다. (HashSet의 기본 개념)
hashcode()
public native int hashCode();
- 자바에서는 hashCode() 메소드를 활용하여, heap에 저장된 해시 알고리즘에 의해 생성 된 고유의 정수 값을 반환한다.
- 객체가 같은 메모리 주소를 가리키고 있다면 같은 정수값을 얻는다.
- native 키워드는 메소드가 JNI(Java Native Interface)라는 native code를 이용해 구현되었음을 의미한다.
hashcode 예제
TestClazz t1 = new TestClazz();
TestClazz t2 = new TestClazz();
TestClazz t3 = t1;
System.out.println("t1 : " + t1.hashCode());
System.out.println("t2 : " + t2.hashCode());
System.out.println("t3 : " + t3.hashCode());
결과
t1 : 2023938592
t2 : 195615004
t3 : 2023938592
그래서 왜 hashcode는 int 값을 반환 할까?
- long 타입도 쓸수 있을텐데 왜 int값을 반환하는가에 궁금증이 생겼다.
- 메모리 효율성
- int는 32비트(4바이트) 정수로, long(8바이트)보다 메모리 사용이 적기 때문에 int를 사용 하면 효율적으로 사용 가능하다.
- 해시 테이블의 설계
- 해시 테이블은 일반적으로 int 값을 사용하여 인덱스를 계산하는데, 해시 코드가 int인 경우, 해시 테이블의 크기와 관련된 연산이 간단해지고, int 범위 내에서 충돌을 처리하는 것이 더 간단하고 효율적이다.
- Java의 설계 철학
- 일관성: Java의 Object 클래스에서 정의된 hashCode() 메서드는 모든 객체에 대해 일관된 방식으로 해시 코드를 제공한다.
- 충분한 해시 공간
- int형은 -2,147,483,648에서 2,147,483,647까지의 값을 가질 수 있고, 대부분의 애플리케이션에서 충분한 해시 공간을 제공한다.
- 해시 테이블의 크기가 커질수록 충돌 가능성이 증가하지만, 적절한 해시 함수를 사용하면 충돌을 최소화할 수 있다.