
리스트는 같은 값을 여러 번 담을 수 있다. 그런데 때로는 "중복 없이" 데이터를 모아야 할 때가 있다. 예를 들어 설문 응답자 목록, 태그 목록처럼 같은 항목이 두 번 들어가면 안 되는 경우다. 이럴 때 쓰는 게 Set이다.
Set은 List와 달리 두 가지 특징이 있다.
중복을 허용하지 않는다. 같은 값을 두 번 추가하면 무시된다.
순서를 보장하지 않는다. 추가한 순서대로 저장되지 않는다.
import java.util.HashSet;
import java.util.Set;
Set<String> set = new HashSet<>();
set.add("사과");
set.add("바나나");
set.add("사과"); // 중복 → 무시됨
System.out.println(set); // [바나나, 사과] (순서는 실행마다 다를 수 있다)
System.out.println(set.size()); // 2
가장 많이 쓰이는 구현체다. 내부적으로 해시 테이블(Hash Table)을 사용한다. 덕분에 추가/삭제/검색이 빠르다. 단, 순서를 전혀 보장하지 않는다.
Set<String> hashSet = new HashSet<>();
hashSet.add("C");
hashSet.add("A");
hashSet.add("B");
System.out.println(hashSet); // [A, B, C] 또는 다른 순서 (보장 없음)
추가한 순서를 유지하는 Set이다. HashSet보다 약간 느리지만, 입력 순서를 보장해야 할 때 쓴다.
import java.util.LinkedHashSet;
Set<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("C");
linkedSet.add("A");
linkedSet.add("B");
System.out.println(linkedSet); // [C, A, B] (입력 순서 유지)
데이터를 정렬된 순서로 유지하는 Set이다. 내부적으로 이진 탐색 트리를 사용한다. 숫자는 오름차순, 문자열은 사전 순으로 자동 정렬된다.
import java.util.TreeSet;
Set<Integer> treeSet = new TreeSet<>();
treeSet.add(3);
treeSet.add(1);
treeSet.add(2);
System.out.println(treeSet); // [1, 2, 3] (자동 정렬)

Set도 List와 마찬가지로 인터페이스다. HashSet, LinkedHashSet, TreeSet 모두 Set 인터페이스를 구현한다.
Set<String> set = new HashSet<>();
set.add("사과"); // 추가 (중복이면 false 반환)
set.remove("사과"); // 삭제
set.contains("바나나"); // 포함 여부
set.size(); // 크기
set.clear(); // 전체 삭제
set.isEmpty(); // 비어있는지 확인
List와 달리 인덱스가 없으므로 get(0) 같은 인덱스 접근은 불가능하다. 순회는 for-each를 쓴다.
for (String item : set) {
System.out.println(item);
}
Set의 가장 실용적인 활용은 중복 제거다. ArrayList에 담긴 데이터에서 중복을 없애고 싶을 때, Set에 넣었다가 다시 꺼내면 된다.
import java.util.*;
List<String> listWithDups = new ArrayList<>(Arrays.asList("사과", "바나나", "사과", "딸기", "바나나"));
Set<String> set = new HashSet<>(listWithDups); // 중복 제거
List<String> result = new ArrayList<>(set); // 다시 List로
System.out.println(result); // [바나나, 사과, 딸기] (순서는 다를 수 있음)
| 구분 | List | Set |
|---|---|---|
| 중복 | 허용 | 불허 |
| 순서 | 유지 | 미보장 (LinkedHashSet 제외) |
| 인덱스 접근 | 가능 | 불가 |
| 대표 구현체 | ArrayList, LinkedList | HashSet, TreeSet |
"담을 데이터가 중복될 수 있냐, 없냐"를 기준으로 List와 Set을 구분하면 된다. 순서가 중요하다면 List, 중복 없이 유일한 값만 모아야 한다면 Set. 그 안에서 정렬이 필요하면 TreeSet, 입력 순서가 필요하면 LinkedHashSet을 선택하면 된다.