여러 자료에서 HashTable 보다는 HashMap을 권장한다. 그러면 정말 HashMap이 좋은지 데이터 추가, 조회, 삭제해보며 이 둘을 비교해보자. 간단한 테스트를 위해 키는 문자열 key + 숫자로 하였다.
성능 비교 코드는 Github에 올려 두었다.
1. 데이터 추가(put)
데이터 추가할 때 걸리는 시간을 비교하고자 하였다.
데이터를 1부터 10000000까지 10의 배수로 넣어가며 비교를 했다.
@Test
public void putTest(){
int dataSizeLimit = 10000000;
int dataSize = 1;
System.out.println("put running time test\\n");
while (dataSize <= dataSizeLimit){
System.out.print("dataSize = "+ String.format("%10d",dataSize) );
Map hashtable = new Hashtable();
System.out.print(", hashTable = " + String.format("%10s", putData(hashtable, dataSize)) );
Map hashMap = new HashMap();
System.out.print(", hashMap = " + String.format("%10s", putData(hashMap, dataSize)) );
dataSize *=10;
System.out.println();
}
}
/**
* put running time test
*
* dataSize = 1, hashTable = 3, hashMap = 0
* dataSize = 10, hashTable = 0, hashMap = 0
* dataSize = 100, hashTable = 0, hashMap = 0
* dataSize = 1000, hashTable = 2, hashMap = 1
* dataSize = 10000, hashTable = 10, hashMap = 9
* dataSize = 100000, hashTable = 61, hashMap = 31
* dataSize = 1000000, hashTable = 339, hashMap = 302
*
* dataSize 가 10000000 이 넘으면 hashTable 에서 OOM 발생
*
* hashTable과 hashMap의 순서를 반대로 했을때
* dataSize = 1, hashMap = 4, hashTable = 0
* dataSize = 10, hashMap = 1, hashTable = 0
* dataSize = 100, hashMap = 1, hashTable = 1
* dataSize = 1000, hashMap = 4, hashTable = 2
* dataSize = 10000, hashMap = 10, hashTable = 9
* dataSize = 100000, hashMap = 73, hashTable = 39
* dataSize = 1000000, hashMap = 421, hashTable = 277
* dataSize = 10000000, hashMap = 3751
*/
private String putData(Map map, int dataSize unt) {
AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
for (int i = 0; i < dataSize ; i++) {
map.put("key"+i, i);
}
return new AtomicLong(System.currentTimeMillis() - startTime.get()).toString();
}
속도 측면에서 이 둘의 성능 차이는 없어 보인다. 하지만 HashTable 은 10000000 이 넘으면 OutOfMemory 예외처리를 발생시킨다. 메모리 관리측면에서 HashMap이 더 좋아 보인다.
2. 데이터 조회(get)
해시의 사이즈가 달라져도 조회가 속도가 유지되는지 보고자 하였다.
조회 건수(getCount)는 100000000 인 상태에서 데이터를 1부터 10000000까지 10의 배수로 넣어가며 비교를 했다.
@Test
public void getTest(){
int dataSizeLimit = 1000000;
int dataSize = 1;
int getCount = 100000000;
System.out.println("get running time test");
System.out.printf("get count = %d\\n\\n", getCount);
while (dataSize <= dataSizeLimit){
System.out.print("dataSize = "+ String.format("%10d",dataSize) );
Map hashtable = new Hashtable();
putData(hashtable, dataSize);
System.out.print(", hashTable = " + String.format("%10s", getHashValue(hashtable, getCount)) );
Map hashMap = new HashMap();
putData(hashMap, dataSize);
System.out.print(", hashMap = " + String.format("%10s", getHashValue(hashMap, getCount)) );
dataSize *=10;
System.out.println();
}
}
/**
* get running time test
* get count = 100000000
*
* dataSize = 1, hashTable = 5962, hashMap = 4699
* dataSize = 10, hashTable = 8385, hashMap = 5922
* dataSize = 100, hashTable = 7280, hashMap = 5671
* dataSize = 1000, hashTable = 7567, hashMap = 6099
* dataSize = 10000, hashTable = 7421, hashMap = 7106
* dataSize = 100000, hashTable = 8895, hashMap = 7870
* dataSize = 1000000, hashTable = 11130, hashMap = 9818
*
*
* hashTable과 hashMap의 순서를 반대로 했을때
* dataSize = 1, hashMap = 4882, hashTable = 6114
* dataSize = 10, hashMap = 5122, hashTable = 7393
* dataSize = 100, hashMap = 5271, hashTable = 6416
* dataSize = 1000, hashMap = 5185, hashTable = 6534
* dataSize = 10000, hashMap = 6143, hashTable = 8745
* dataSize = 100000, hashMap = 7551, hashTable = 9024
* dataSize = 1000000, hashMap = 9270, hashTable = 11956
*/
private String getHashValue(Map map, int dataSize) {
AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
for (int i = 0; i < dataSize; i++) {
map.get("key"+i);
}
return new AtomicLong(System.currentTimeMillis() - startTime.get()).toString();
}
데이터 사이즈가 증가 함에 따라 조회하는 시간이 증가하지만 그 폭이 데이터 사이즈의 증가 폭보다는 훨씬 덜하다. 조회 속도는 HashMap 이 더 빠른 것을 볼 수 있다.
3. 데이터 삭제(remove)
데이터 삭제할 때 걸리는 시간을 비교하고자 하였다.
데이터를 1부터 1000000까지 10의 배수로 넣어은 상태에서 데이터를 하나씩 삭제는 시간을 구하여 비교했다.
@Test
public void removeKeyTest(){
int dataSizeLimit = 1000000;
int dataSize = 1;
System.out.println("remove running time test\\n");
while (dataSize <= dataSizeLimit){
System.out.print("dataSize = "+ String.format("%10d",dataSize) );
Map hashtable = new Hashtable();
putData(hashtable, dataSize);
System.out.print(", hashTable = " + String.format("%10s", removeKey(hashtable, dataSize)) );
Map hashMap = new HashMap();
putData(hashMap, dataSize);
System.out.print(", hashMap = " + String.format("%10s", removeKey(hashMap, dataSize)) );
dataSize *=10;
System.out.println();
}
}
/**
* remove running time test
*
* dataSize = 1, hashTable = 0, hashMap = 0
* dataSize = 10, hashTable = 0, hashMap = 0
* dataSize = 100, hashTable = 0, hashMap = 0
* dataSize = 1000, hashTable = 2, hashMap = 1
* dataSize = 10000, hashTable = 5, hashMap = 4
* dataSize = 100000, hashTable = 20, hashMap = 17
* dataSize = 1000000, hashTable = 169, hashMap = 156
*
* hashTable과 hashMap의 순서를 반대로 했을때
* dataSize = 1, hashMap = 1, hashTable = 0
* dataSize = 10, hashMap = 0, hashTable = 0
* dataSize = 100, hashMap = 0, hashTable = 1
* dataSize = 1000, hashMap = 2, hashTable = 1
* dataSize = 10000, hashMap = 7, hashTable = 4
* dataSize = 100000, hashMap = 18, hashTable = 25
* dataSize = 1000000, hashMap = 167, hashTable = 270
*/
private String removeKey(Map map, int dataSize) {
AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
for (int i = 0; i < dataSize; i++) {
map.remove("key"+i);
}
return new AtomicLong(System.currentTimeMillis() - startTime.get()).toString();
}
삭제 속도가 HashMap이 더 좋은 것을 볼 수 있다.
자료구조 시리즈
4. JAVA ArrayList와 LinkedList 성능 비교 - 자료구조(4)
5. JAVA Queue 그리고 offer, poll , peek - 자료구조(5)
6. JAVA 왜 Stack 은 Array로, Queue는 LinkedList로 구현 했을까? - 자료구조(6)
7. JAVA Hash 그리고 HashMap 과 HashTable - 자료구조(7)
8. JAVA HashMap 과 HashSet의 성능 비교 - 자료구조(8)
'개발' 카테고리의 다른 글
| 디자인 패턴을 적용해보자 - 팩토리(1). (pizza 예제 아님) (0) | 2023.04.05 |
|---|---|
| JAVA HashMap의 용량은 왜 2의 거듭제곱일까? - 자료구조(9) (0) | 2022.05.30 |
| JAVA Hash 그리고 HashMap 과 HashTable - 자료구조(7) (0) | 2022.05.30 |
| JAVA 왜 Stack 은 Array로, Queue는 LinkedList로 구현 했을까? - 자료구조(6) (0) | 2022.05.30 |
| JAVA Queue 그리고 offer, poll , peek - 자료구조(5) (0) | 2022.05.30 |