자바에서 Set은 중복을 허용하지 않는 컬렉션(Collection)이다.
즉, 같은 값을 여러 번 넣으려고 해도 한 번만 저장된다.
Set은 java.util 패키지에 있고, 인터페이스 형태로 존재하며, 다음과 같은 상속 관계를 가지고 있다.
1. Set의 상속 구조 (인터페이스 중심)
java.lang.Iterable<E>
↑
java.util.Collection<E>
↑
java.util.Set<E> // 아래는 Set의 구현 클래스들이다.
├── HashSet<E>
│ └── LinkedHashSet<E>
└── SortedSet<E>
└── NavigableSet<E>
└── TreeSet<E>
2. Set의 대표적인 구현체(클래스)
대표적인 구현체로는 다음과 같은 것들이 있다:
2-1. HashSet
- 가장 많이 사용되는 Set 구현체
- 내부적으로 HashMap을 사용하여 구현됨
- 순서를 보장하지 않음
- null 값을 하나 저장할 수 있음
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
set.add("apple"); // 중복이므로 무시됨
System.out.println(set); // 출력: [banana, apple] (순서는 보장되지 않음)
2-2. LinkedHashSet
- HashSet과 거의 같지만, 입력 순서를 유지함
- 내부적으로 LinkedList + HashMap 구조
Set<String> set = new LinkedHashSet<>();
set.add("apple");
set.add("banana");
set.add("cherry");
System.out.println(set); // 출력: [apple, banana, cherry]
3-3. TreeSet
- 정렬된 상태로 저장됨
- 기본은 오름차순 정렬 (또는 Comparator 사용 가능)
- 내부적으로 Red-Black Tree 구조
Set<Integer> set = new TreeSet<>();
set.add(3);
set.add(1);
set.add(2);
System.out.println(set); // 출력: [1, 2, 3]
4.주요 메서드 요약 (Set 인터페이스 공통)
메서드 | 설명 |
add(E e) | 요소 추가 (중복이면 추가 안 됨) |
remove(Object o) | 요소 제거 |
contains(Object o) | 포함 여부 확인 |
size() | 크기 확인 |
clear() | 전체 요소 삭제 |
isEmpty() | 비어 있는지 확인 |
iterator() | 반복자 반환 (향상된 for문 사용 가능) |
- Collections를 상속 받기에 Collections의 메서드들을 대부분 이용 가능하다.
5. Set 구현체의 시간 및 공간 복잡도
일전에 코딩 테스트 공부하다가 각 자료구조의 시간복잡도와 공간 복잡도에 대해 찾아본적이 있다.
하여 대표적으로 사용되는 구현체들의 시간복잡도에 대해 적어본다.
5-1. HashSet
- 기반 자료구조: HashMap
- 해시 함수를 기반으로 하기 때문에 빠름
연산 | 평균 시간복잡도 | 최악 시간복잡도 |
add, remove, contains | O(1) | O(n) |
size, isEmpty | O(1) | O(1) |
최악의 경우는 해시 충돌이 많이 날 때, 내부적으로 연결 리스트나 트리로 변형되면서 느려질 수 있음
- 공간복잡도: O(n)
- 요소 저장 외에도 내부적으로 해시 버킷 배열이 필요함
5-2. LinkedHashSet
- 기반 자료구조: HashMap + LinkedList
- 입력 순서를 유지하기 위해 연결 리스트 추가됨
연산 | 평균 시간복잡도 | 최악 시간복잡도 |
add, remove, contains | O(1) | O(n) |
- 공간복잡도: O(n)
- HashSet보다 약간 더 많은 메모리를 사용 (순서를 기억하는 연결 포인터 때문에)
5-3. TreeSet
- 기반 자료구조: TreeMap (구체적으로 Red-Black Tree)
- 정렬이 필요할 때 사용
연산 | 시간복잡도 |
add, remove, contains | O(log n) |
first, last, ceiling, floor | O(log n) |
- 공간복잡도: O(n)
- 균형 트리 구조를 유지하기 위한 포인터들이 추가됨
5-4. 요약
구현체 | 시간복잡도 | 공간복잡도 | 특징 |
HashSet | 평균 O(1), 최악 O(n) | O(n) | 가장 빠름, 순서 없음 |
LinkedHashSet | 평균 O(1), 최악 O(n) | O(n) | 입력 순서 유지 |
TreeSet | O(log n) | O(n) | 자동 정렬, 느림 |
- 순서 필요 없다 + 빠른 성능 원함 → HashSet
- 입력 순서 필요 → LinkedHashSet
- 정렬된 데이터 필요 → TreeSet
6. 언제 사용되는가?
Set은 기본적으로 중복 없이 데이터만 저장하고 싶을 때 쓴다.
Map도 마찬가지로 키의 중복 없이 데이터를 저장을 하지만 값을 중복 없이 저장하지는 않는다.
추가로 Map은 <key,boolean> 형식으로 존재 여부 확인용으로 Set처럼 쓸 수 있지만 메모리 낭비에 가독성도 떨어진다.
예시 상황 :
- 유저 ID -> 중복 없는 데이터 리스트 만들기
- 방문한 페이지 집합 관리
Set<String> visitedPages = new HashSet<>();
visitedPages.add("homePage"); // 홈페이지 방문
visitedPages.add("aboutPage"); // 정보소개 페이지 방문
visitedPages.add("homePage"); // 홈페이지 방문 중복, 무시됨
7. 다른 구현체로 변환
// Set → List
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
List<String> list = new ArrayList<>(set);
System.out.println(list); // [banana, apple] — 순서는 보장 안 됨
// List → Set
List<String> list = Arrays.asList("apple", "banana", "apple");
Set<String> setFromList = new HashSet<>(list); // 중복 제거됨
// Set → 배열
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
Object[] arr = set.toArray(); // Object 배열 반환
// 배열 → Set
String[] fruits = {"apple", "banana", "apple"};
Set<String> setFromArray = new HashSet<>(Arrays.asList(fruits));
'공부 > 자바(Java)' 카테고리의 다른 글
Java) 람다식(Lambda expression)과 함수형 인터페이스란? (0) | 2025.04.06 |
---|---|
Java) Stream API란? (0) | 2025.04.06 |
Java) Arrays VS Collections | ( Arrays와 Collections의 간단 설명, 사용법, 예제) (0) | 2025.04.05 |
Java) Queue란? (큐 간단 설명, 사용법, 예제) (3) | 2025.04.05 |
Java) Stack이란? (간단 설명, 사용법, 예시) (0) | 2025.04.05 |