| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 객체지향
- 자바공부
- 코딩공부
- 개발자팁
- 가비지컬렉션
- 프로그래밍기초
- 자바기초
- Java
- 자료구조
- HashMap
- 예외처리
- 자바프로그래밍
- JVM
- 메모리관리
- 개발공부
- 알고리즘공부
- 자바
- 백준
- 클린코드
- 코딩테스트팁
- 정렬
- 코딩인터뷰
- 프로그래머스
- 멀티스레드
- 코딩테스트
- 개발자취업
- 알고리즘
- 코딩테스트준비
- 자바개발
- 파이썬
- Today
- Total
코드 한 줄의 기록
Java HashSet, TreeSet, LinkedHashSet 완벽 정리 - 특성과 정렬 방법 본문
자바로 개발하다 보면 중복 없이 데이터를 관리해야 하는 경우가 정말 많습니다. 이럴 때 Set 컬렉션을 사용하는데, 막상 HashSet, TreeSet, LinkedHashSet 중에서 어떤 것을 선택해야 할지 고민될 때가 있죠. 오늘은 제가 공부한 내용을 정리하면서, 여러분께도 각 Set의 특성과 정렬 방법을 공유해보려고 합니다.
Set 인터페이스의 기본 특징
먼저 Set이 무엇인지부터 정리하고 넘어가겠습니다. Set은 Collection 인터페이스를 상속받은 인터페이스로, 중복을 허용하지 않는다는 것이 가장 큰 특징입니다. List처럼 같은 값을 여러 번 저장할 수 없고, 한 번만 저장됩니다.
- 중복된 값을 저장할 수 없음
- 기본적으로 순서를 보장하지 않음 (일부 구현체 제외)
- 인덱스로 접근 불가능
- null 값도 한 번만 저장 가능
HashSet - 가장 빠른 성능의 기본 Set
HashSet은 Set 인터페이스의 가장 기본적인 구현체입니다. 실무에서 가장 많이 사용하는 Set이기도 하죠.
HashSet의 내부 구조
private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT) == null;
}
HashMap의 Key에 저장하려는 데이터를 넣고, Value에는 PRESENT라는 더미 객체를 넣습니다. HashMap은 Key의 중복을 허용하지 않으니까, 자연스럽게 중복 제거가 되는 원리입니다.
HashSet의 특징
장점
- 검색, 삽입, 삭제 연산이 평균 O(1) 시간 복잡도를 가짐
- 세 가지 Set 중에서 가장 빠른 성능
- 대용량 데이터 처리에 적합
단점
- 저장 순서를 전혀 보장하지 않음
- 정렬된 상태로 유지되지 않음
중복 체크 원리
HashSet이 중복을 판단하는 원리는 hashCode()와 equals()를 이용하는 것입니다.
public class Member {
private String name;
private int age;
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Member) {
Member m = (Member) obj;
return name.equals(m.name) && age == m.age;
}
return false;
}
}
HashSet 사용 예시
Set<String> fruits = new HashSet<>();
fruits.add("사과");
fruits.add("바나나");
fruits.add("오렌지");
fruits.add("사과");
System.out.println(fruits);
TreeSet - 자동 정렬되는 Set
TreeSet은 정렬이 필요한 상황에서 유용합니다. 순위 시스템이나 범위 검색이 필요할 때 자주 사용됩니다.
TreeSet의 내부 구조
TreeSet은 Red-Black Tree로 구현되어 있습니다. 내부적으로 TreeMap을 활용합니다.
private transient NavigableMap<E,Object> m;
public TreeSet() {
this(new TreeMap<E,Object>());
}
TreeSet의 특징
- 저장 시 자동 오름차순 정렬
- Comparator로 정렬 기준 변경 가능
- 범위 검색 메서드 지원 (
subSet(),headSet()) - O(log n) 복잡도
TreeSet 사용 예시
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(30);
numbers.add(10);
numbers.add(20);
numbers.add(50);
System.out.println(numbers);
Comparator 활용
TreeSet<Integer> desc = new TreeSet<>(Collections.reverseOrder());
desc.add(10);
desc.add(20);
desc.add(30);
System.out.println(desc);
LinkedHashSet - 입력 순서를 기억하는 Set
LinkedHashSet은 HashSet과 거의 같지만, 삽입 순서를 기억합니다.
LinkedHashSet 사용 예시
Set<String> linkedSet = new LinkedHashSet<>();
linkedSet.add("첫번째");
linkedSet.add("두번째");
linkedSet.add("세번째");
System.out.println(linkedSet);
LinkedHashSet 특성
- 입력 순서 보장
- HashSet보다 약간 느림
- 평균 O(1) 성능
세 가지 Set 비교
| 특징 | HashSet | LinkedHashSet | TreeSet |
| 내부 구조 | HashMap | LinkedHashMap | TreeMap (Red-Black Tree) |
| 순서 보장 | X | O (삽입 순서) | O (정렬 순서) |
| 시간 복잡도 | O(1) | O(1) | O(log n) |
| 정렬 | X | 입력순만 | 자동정렬 |
Set 정렬 방법
1. TreeSet으로 변환
TreeSet<Integer> sorted = new TreeSet<>(hashSet);
System.out.println(sorted);
2. List로 변환 + Collections.sort()
List<String> list = new ArrayList<>(fruits);
Collections.sort(list);
3. Stream API 활용
List<Integer> sortedList = numbers.stream()
.sorted()
.collect(Collectors.toList());
HashSet : 빠르고 단순한 중복 제거용
LinkedHashSet : 순서 보존 + 중복 제거
TreeSet : 정렬이 필요한 경우
정렬이 필요하다면 TreeSet, Collections.sort(), Stream.sorted() 중에서 선택하면 됩니다. 실무에서는 대부분 HashSet을 사용하고, 필요할 때만 변환하여 정렬하는 방식이 효율적입니다.
코드를 작성하다가 중복 제거와 정렬이 동시에 필요할 때, 이 글이 도움이 되길 바랍니다!
'JAVA' 카테고리의 다른 글
| Java Queue, Deque, PriorityQueue 완벽 가이드 (0) | 2025.10.27 |
|---|---|
| Java Map 완전 정복: HashMap, LinkedHashMap, TreeMap 비교와 키 설계 핵심 가이드 (0) | 2025.10.26 |
| ArrayList vs LinkedList 언제 어떤 걸 써야 할까? (0) | 2025.10.25 |
| Java 컬렉션 프레임워크 이해하기: List/Set/Map 완벽 가이드 (0) | 2025.10.24 |
| Java 로깅 완벽 가이드: SLF4J와 로그 레벨 이해 (0) | 2025.10.19 |