HashSet은 내부적으로 HashMap을 사용하고, HashMap은 다시 “버킷 배열(배열) + 각 버킷에서의 연결 리스트 혹은 트리(레드-블랙 트리)”로 구성됩니다.
1) 해싱의 목적
특정 키(Key)를 해시 함수에 넣어, 그 결과(해시 값)를 인덱스로 삼아 요소를 저장합니다. 이로 인해 평균 O(1)에 가까운 접근이 가능해집니다.
2) 해시 함수
객체(또는 값) -> 정수로 매핑하는 함수입니다. HashSet은 이 값을 바탕으로 객체가 들어갈 자리(버킷bucket)를 결정합니다.

1) 배열(Array) + 연결 리스트(또는 트리 구조)
내부적으로는 해시 버킷(버킷 배열)을 가지고 있습니다. 중복되는 해시 값이 나오는 경우 하나의 버킷에 여러 요소를 담을 수 있도록 버킷 하나하나는 연결 리스트(Linked List)나 트리(Tree) 형태로 관리됩니다.
2) HashSet vs HashMap
Java의 HashSet은 사실상 내부에서 HashMap을 활용합니다. HashSet에 값을 추가하면 내부적으로 HashMap의 key로 사용됩니다(Value는 dummy 값).

HashSet에 원소를 추가한다는 것은 내부적으로 HashMap.put(key, dummyValue)를 호출하는 것과 같습니다.
Java HashMap의 put 동작을 예시로 설명해보면 다음과 같은 단계를 거칩니다.
1. hashCode() 호출 및 해시 값 생성
hashCode()를 호출합니다.2. 버킷 인덱스 계산
index = (hash & (table.length - 1)) (비트 연산 형태)index = hash % table.length와 유사한 효과지만, 비트 마스크 연산으로 최적화된 형태를 취합니다.3. 해당 버킷 탐색 및 연결 리스트/트리 확인
4. 트리화(Treeify) 혹은 해시 충돌 처리
5. 리사이징(Resize) 검사
capacity * loadFactor를 초과하면 버킷 배열 크기를 두 배로 늘립니다.loadFactor는 0.75, 기본 capacity는 16 → 12개를 초과하면 리사이징 발생rehash 과정(인덱스 재계산)이 진행됩니다.6. 결과
정리하자면, HashSet의 add는 내부적으로 해시 값 → 버킷 찾기 → 해당 버킷 노드들 확인(equals) → 새 노드 삽입 → 필요 시 트리화, 리사이징 과정을 거칩니다.

충돌 처리 예시. Open Addressing과 Seperate Chaining형식이 있다.
HashSet에 원소가 존재하는지 확인하는 과정은 내부적으로 HashMap.containsKey(key)와 동일합니다.
1. hashCode() 호출 및 해시 값 생성
hashCode()를 구하고, HashMap의 해싱 로직에 따라 최종 해시 값을 결정합니다.2. 버킷 인덱스 계산
index = (hash & (table.length - 1)) 형태로 버킷 위치를 알아냅니다.3. 노드 검색
4. 트리인 경우
HashSet에서 원소를 제거하는 것은 내부적으로 HashMap.remove(key)를 호출하는 것과 동일합니다.
1. hashCode() 호출 및 인덱스 계산
hashCode() → 해시 함수 적용 → (hash & (table.length - 1))로 버킷 인덱스 결정.2. 해당 버킷에서 노드 탐색
equals()로 동일한 노드를 찾습니다.3. 노드 제거
4. size 감소
remove 과정도 결론적으로 “hash → 인덱스 → 연결 리스트 혹은 트리에서 노드 탐색 → 제거 및 링크 혹은 트리 재조정” 식으로 정리할 수 있습니다.
1. 삽입 (add)
2. 검색 (contains)
3. 삭제 (remove)
결론적으로 해시 함수와 동등성 비교(equals)가 잘 설계되어 있어야, 해시 충돌이 줄어들고 삽입/검색/삭제 모두 평균 O(1) 성능을 유지할 수 있습니다. 충돌이 심하면 연결 리스트/트리를 많이 탐색해야 하므로 최악의 경우 O(n)으로 악화될 수도 있습니다.
Load Factor (기본: 0.75)
너무 충돌이 많아지지 않도록, 최대 적재량이 넘으면 배열 크기를 2배로 늘립니다(Resizing + Rehash).
트리 변환(Chain to Tree)
정렬 순서 보장 없음
중복 원소 없음
이미지 출처 : yoseph0310.tistory.com