HashTable(해쉬테이블)
- key와 value를 대응시켜 저장하는 선형 데이터 구조
- key 를 통해 해당 데이터에 빠르게 접근 가능
- 키를 특정 계산식에 넣어 나온 결과를 사용하여 값에 접근하는 과정을 Hashing이라고 함
- 병렬 프로그래밍을 지원하여 병렬 처리를 하면서 자원의 동기화를 고려해야 하는 상황일 때 사용하기 적합
해시 충돌 해결 방법
1. 개방 주소법(Open Address) : 충돌 시, 테이블에서 비어있는 공간의 hash를 찾아 데이터를 저장하고
hash와 value가 1:1 관계 유지
비어있는 공간 탐색 방법에 따라 분류
- 선형 탐사법(Linear Probing) : 충돌 발생 지점부터 이후의 빈 공간을 순차적으로 탐사,
반복된 충돌 발생시 해당 지점 주변에 데이터가 몰리는 경우 일차 군집화 문제 발생
- 제곱 탐사법(Quadratic Probing) : 충돌 발생 지점부터 이후의 빈 공간을 n 제곱 만큼의 간격을 투고 탐사,
일차 군집화 문제 일부를 보완했지만 이차 군집화 문제 발생 가능성이 있음
- 이중 해싱 (Double Hashing) : 해싱 함수를 이중으로 사용(1: 최소 해서 구할 때 / 2: 충돌 발생시 탐사 이동 간격
구할 때), 선형 탐사, 제곱 탐사에 비해 데이터가 골고루 분포됨
2. 분리 연결법(Seperate Chaining) : 해시 테이블을 연결 리스트로 구성,
충돌 발생 시 테이블 내의 다른 위치를 탐색하는 것이 아닌 연결 리스트를 이용하여 해당 테이블에 데이터를 연결
HashTable 시간복잡도
접근, 탐색 , 추가 , 삭제 : O(1)
연산 | |
put(Object key, Object value) | key-value 쌍을 추가 |
get(Object key) | 지정된 key에 해당하는 value를 반환 |
remove(Object key) | 지정된 key와 해당하는 value를 제거 |
containsKey(Object key) | 지정된 key가 Hashtable에 포함되어 있는지 여부를 반환 (있으면 true) |
keys() | 모든 key를 담은 Enumeration을 반환 (있으면 true) |
size( ) | Hashtable의 key-value 쌍의 수를 반환 |
clear() | Hashtable의 모든 key-value 쌍을 제거 |
//해시테이블 사용예제
import java.util.Hashtable;
import java.util.Map;
//20240227
public class hashTable {
//해시 함수
public static int getHash(int key){
return key % 5;
}
public static void main(String[] args){
//기본 해시 테이블 사용 방법
Hashtable<String, Integer> ht = new Hashtable();
ht.put("key1" , 10);
ht.put("key2" , 20);
ht.put("key3" , 30);
System.out.println("test01");
for (Map.Entry<String , Integer> item : ht.entrySet()){
System.out.println(item.getKey() + " - " + item.getValue());
}
//해시 충돌 케이스 (해시 함수 사용)
Hashtable<Integer, Integer> ht2 = new Hashtable();
ht2.put(getHash(1), 10);
ht2.put(getHash(2), 20);
ht2.put(getHash(3), 30);
ht2.put(getHash(4), 40);
ht2.put(getHash(5), 50);
System.out.println("test02");
System.out.println("=== 충돌 전 ===");
for (Map.Entry<Integer , Integer> item : ht2.entrySet()){
System.out.println(item.getKey() + " - " + item.getValue());
}
ht2.put(getHash(6), 60);
System.out.println("=== 충돌 후 ===");
for (Map.Entry<Integer , Integer> item : ht2.entrySet()){
System.out.println(item.getKey() + " - " + item.getValue());
}
}
}
import java.util.Hashtable;
import java.util.Map;
//20240227
//해시 테이블 - 배열로 직접 구현
class MyHashTable{
Integer[] table;
int elemCnt;
MyHashTable(){}
MyHashTable(int size){
this.table = new Integer[size];
this.elemCnt = 0;
}
public int getHash(int key){
return key% this.table.length;
}
public void setValue(int key, int data){
int idx = this.getHash(key);
this.table[idx] = data;
this.elemCnt++;
}
public int getValue(int key){
int idx = this.getHash(key);
return this.table[idx];
}
public void removeValue(int key){
int idx = this.getHash(key);
this.table[idx] = null;
this.elemCnt--;
}
public void printHashTable(){
System.out.println("=== Hash Table ===");
for (int i = 0; i < this.table.length; i++) {
System.out.println(i + " : " + this.table[i]);
}
}
}
public class hashTablePractice01 {
public static void main(String[] args){
//Test code
MyHashTable ht = new MyHashTable(7);
ht.setValue(1, 1);
ht.setValue(2, 2);
ht.setValue(3, 3);
ht.setValue(4, 4);
ht.setValue(5, 5);
ht.printHashTable();
ht.setValue(8, 6);
ht.printHashTable();
}
}
장점
- 빠른 검색 및 삽입 : 해시 함수를 사용해 데이터를 저장하므로 데이터에 접근하는 데 상수 시간(O(1))이 소요된다. 따라서 매우 빠른 검색과 삽입이 가능하다.
- 유연한 크기 조정 : 데이터의 개수에 따라 자동으로 크기를 조정할 수 있다. 이를 통해 메모리 공간의 효율성을 유지하면서도 높은 성능을 유지할 수 있다.
- 다양한 용도로 활용 가능 : 캐싱, 데이터베이스 인덱싱, 중복 검사 등에 사용될 수 있다.
단점
- 해시 충돌 : 서로 다른 키가 동일한 해시 값에 매핑될 수 있는 해시 충돌이 발생할 수 있다. 충돌이 자주 발생하면 검색 및 삽입 연산의 성능이 저하될 수 있다. 충돌을 해결하기 위해 충돌 해결 방법을 선택해야 합니다.
- 메모리 사용량 : 해시 버킷과 해시 함수를 사용하기 때문에 일정한 메모리 공간을 필요로 하다. 특히 데이터의 수가 많을 경우 메모리 사용량이 증가할 수 있다.
- 순서의 무작위성 : 키의 해시 값을 기반으로 데이터를 저장하기 때문에 데이터의 순서가 무작위로 보여진다. 데이터를 순차적으로 접근하는 것이 필요한 경우에는 Hash Table보다는 다른 자료구조를 고려하는 것이 좋다.
HashMap과 Hashtable 클래스의 차이점
- Thread-safe 여부
Hashtable은 Thread-safe하고, HashMap은 Thread-safe하지 않다. 그렇기에 멀티스레드 환경이 아니라면 Hashtable은 HashMap 보다 성능이 떨어진다.
- Null 값 허용 여부
Hashtable은 key에 null을 허용하지 않지만, HashMap은 key에 null을 허용한다.
- Enumeration 여부
Hashtable은 not fail-fast Enumeration을 제공하지만, HashMap은 Enumeration을 제공하지 않는다.
HashMap은 보조해시를 사용하기 때문에 보조 해시 함수를 사용하지 않는 Hashtable에 비하여 해시 충돌(hash collision)이 덜 발생할 수 있어 상대적으로 성능상 이점이 있다.
최근까지 Hashtable은 구현에 거의 변화가 없지만, HashMap은 현재까지도 지속적으로 개선되고 있다.
관련link
https://hoehen-flug.tistory.com/35
[자료구조] 해시 테이블(Hash Table) 자료구조 알아보기 & Java 예제 코드
자료구조 중 해시 테이블(Hash Table)에 대해 알아보자. 해시 테이블(Hash Table)이란? 해시 테이블(Hash Table)은 효율적인 검색과 삽입 연산을 위해 설계된 자료구조다. 이는 키-값 쌍의 데이터를 저장하
hoehen-flug.tistory.com
https://velog.io/@realgreatcode/%ED%95%B4%EC%8B%9C-%ED%85%8C%EC%9D%B4%EB%B8%94-Hash-Table
해시테이블 HashTable
해시테이블 Hash Table 키Key와 값Value의 쌍으로 이루어진 자료구조입니다.
velog.io
https://ittrue.tistory.com/153
[Java] 자바 HashTable 개념 정리 및 활용
HashTable HashTable은 HashMap과 내부 구조가 동일하며, 사용 방법 또한 매우 유사하다. HashMap과 마찬가지로 키는 중복이 안되지만, 값은 중복을 허용한다. HashTable과 HashMap의 차이점은 스레드와 관련이
ittrue.tistory.com
https://devlog-wjdrbs96.tistory.com/253
[Java] HashMap vs Hashtable 차이는 무엇일까?
Hashtable 이란? Hashtable 클래스는 컬렉션 프레임웍이 만들어지기 이전부터 존재하던 것이기 때문에 컬렉션 프레임워의 명명법을 따르지 않습니다. Vector나 Hashtable과 같은 기존의 컬렉션 클래스들
devlog-wjdrbs96.tistory.com
'Study for Backend > Data Structure' 카테고리의 다른 글
[Data Structure 기초연습] HashTable - 해시 충돌 해결 - 개방 주소법 ( 제곱 탐사법 ) (0) | 2024.02.29 |
---|---|
[Data Structure 기초연습] HashTable - 해시 충돌 해결 - 개방 주소법 ( 선형 탐사법 ) (0) | 2024.02.29 |
[Data Structure 기초] Heap (1) | 2024.02.24 |
[Data Structure 기초] Deque (0) | 2024.02.23 |
[Data Structure 기초] Linked List (0) | 2024.02.23 |