
— 해시 기반 컬렉션의 핵심 이해하기
자바에서 데이터를 다루다 보면
배열, ArrayList 다음 단계에서 반드시 만나게 되는 컬렉션이 있다.
바로 HashMap 과 HashSet 이다.
처음에는 그냥 “중복 안되는 자료구조”,
“Key-Value 형태” 정도로 외웠지만,
직접 사용해보니 구조적으로 이해하는 게 훨씬 중요하다는 걸 느꼈다.
HashMap<String, Integer> map = new HashMap<>();
HashMap은
🔑 Key : Value 형태로 데이터를 저장하는 컬렉션
특징
map.put("student1", 80);
즉, key가 기준이다.
HashMap은 내부적으로
해시 함수 → 버킷(bucket) → 연결 구조
형태로 저장된다.
Key의 hashCode() 값을 이용해 저장 위치를 빠르게 찾는다.
그래서 인덱스 접근은 없지만
검색이 매우 빠르다.
for(Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
✔ key와 value를 동시에 접근 가능
✔ 가장 효율적
Iterator<Map.Entry<String, Integer>> iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, Integer> entry = iter.next();
System.out.println(entry.getValue());
}
Iterator는
다음 객체가 있는지 확인 → 다음 객체로 이동
하는 구조다.
⚠ next()는 "값 반환 + 포인터 이동"이 동시에 일어나므로
반복문 안에서 한 번만 호출해야 한다.
반복 중 삭제를 할 때 필요하다.
Iterator<Map.Entry<String, Integer>> iter = map.entrySet().iterator();
while(iter.hasNext()) {
Map.Entry<String, Integer> entry = iter.next();
if(entry.getValue() < 60) {
iter.remove(); // 안전한 삭제
}
}
for-each 중에 map.remove()를 사용하면
ConcurrentModificationException 이 발생한다.
HashSet<String> set = new HashSet<>();
HashSet은
중복을 허용하지 않는 자료구조
특징
ArrayList<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple");
HashSet<String> set = new HashSet<>(list);
System.out.println(set);
// [apple, banana]
자동으로 중복 제거됨.
| 구분 | HashMap | HashSet |
|---|---|---|
| 저장 형태 | Key-Value | Value |
| 중복 기준 | Key | Value |
| 순서 | 없음 | 없음 |
| 검색 속도 | 빠름 | 빠름 |
사실 HashSet은 내부적으로
HashMap을 기반으로 구현되어 있다.
즉,
HashSet<String>
은 내부적으로
HashMap<String, Object>
형태로 동작한다.
Value는 의미 없는 더미 객체다.
그래서 해시 기반 구조는 동일하다.
✔ 빠른 검색이 필요할 때
✔ 중복 제거가 필요할 때
✔ 순서가 중요하지 않을 때
배열 → ArrayList → Set/Map
으로 오면서 느낀 건
인덱스 기반 사고에서
"해시 기반 사고"로 전환되는 지점이라는 것
이걸 이해하면
자료구조의 절반은 넘어가는 것 같다.