Set 자료구조는 오직 고유한 값(unique values)만 저장하도록 설계되어 있습니다. 즉, Set에는 중복된 값이 절대 저장되지 않습니다. 그렇다면 HashSet은 어떻게 중복을 걸러낼까요? 비밀은 바로 내부 구현에 있습니다.
HashSet은 내부적으로 HashMap을 사용한다
HashSet 객체가 생성되면, 내부적으로는 HashMap이 함께 만들어집니다. HashSet에 요소를 추가할 때 우리가 호출하는 것은 add() 메서드이지만, 실제로는 내부에 존재하는 HashMap의 put() 메서드가 호출됩니다. 결국 Set은 HashMap의 힘을 빌려 중복 없는 값만 유지하게 되는 것입니다.
put() 메서드의 반환값
HashMap은 고유한 키(key)와 값(value)의 쌍으로 데이터를 관리하며, put() 메서드를 통해 키-값 쌍을 삽입합니다. put() 메서드가 호출되면 해당 키에 대한 매핑이 이미 존재하는지 여부에 따라 다음과 같이 동작합니다.
- 키에 대한 기존 매핑이 있는 경우 → 이전에 연결되어 있던 값을 반환
- 키에 대한 매핑이 없는 경우 → null을 반환
LinkedHashSet과의 관계
LinkedHashSet은 HashSet 클래스를 상속(extends)합니다. 따라서 LinkedHashSet은 super 키워드를 사용하여 HashSet 클래스의 생성자를 호출하며, HashSet의 내부 구현을 그대로 활용하면서 삽입 순서를 유지하는 기능을 추가합니다.
예제 코드
import java.util.HashSet;
public class Demo{
public static void main(String args[]){
HashSet my_hashset = new HashSet();
boolean my_b1 = my_hashset.add("only");
boolean my_b2 = my_hashset.add("sample");
boolean my_b3 = my_hashset.add("sample");
System.out.println("The value of first boolean is " + my_b1);
System.out.println("The value of second boolean is = "+my_b2);
System.out.println("The value of third boolean is = "+my_b3);
System.out.println(my_hashset);
}
}실행 결과
The value of first boolean is true The value of second boolean is = true The value of third boolean is = false [only, sample]
코드 분석
위 예제에서 Demo 클래스의 main 메서드 안에서 HashSet 인스턴스가 생성됩니다. add() 메서드를 사용해 문자열 요소들을 HashSet에 추가하고, 각 호출의 boolean 반환값과 최종 HashSet의 내용을 화면에 출력합니다.
결과를 자세히 살펴보면 다음과 같습니다.
- 첫 번째 add("only") → true : 새로운 요소이므로 정상적으로 추가됩니다.
- 두 번째 add("sample") → true : "sample"도 처음 추가되는 요소이므로 true를 반환합니다.
- 세 번째 add("sample") → false : "sample"은 이미 존재하는 중복 요소이므로 추가되지 않고 false를 반환합니다.
마지막 출력에서 [only, sample]만 확인할 수 있는 이유도 바로 이 때문입니다. HashSet은 add() 메서드의 반환값을 통해 요소의 추가 성공 여부를 알려주며, 내부적으로 HashMap의 put() 메서드가 반환하는 기존 값의 존재 여부를 판단하여 중복 삽입을 자연스럽게 차단합니다.