Java를 활용하다 보면 데이터를 유지하면서 중복을 허용하지 않고, 순서가 중요한 경우가 있습니다. 이때 사용할 수 있는 자료구조 중 하나가 LinkedHashSet입니다.
이 글에서는 Java의 LinkedHashSet에 대해 알아보고, 사용 방법과 예제를 통해 그 장단점을 살펴보겠습니다.
LinkedHashSet의 동작방식
위 그림에서 알 수 있듯이 LinkedHashSet은 내부적으로 해시 테이블(Hash Table)과 링크드 리스트(Linked List)를 조합하여 구현된 자료구조입니다.
- 해시 테이블(Hash Table):
- 해시 테이블은 빠른 데이터 접근을 위한 구조로, 데이터를 저장할 때 각 데이터의 해시 코드를 계산하여 해당 코드에 맞는 인덱스에 데이터를 저장합니다.
- 해시 테이블을 사용하므로 데이터에 대한 검색, 삽입, 삭제 연산이 평균적으로 O(1)의 시간 복잡도로 수행될 수 있습니다.
- 링크드 리스트(Linked List):
- LinkedHashSet은 해시 테이블의 각 버킷(bucket)에 Linked list로 연결된 형태로 데이터를 저장합니다.
- 이 linked list는 데이터의 순서를 유지하기 위해 사용됩니다. 따라서 데이터가 추가된 순서대로 반복문 등을 통해 접근할 수 있습니다.
- 구성 및 동작 방식:
- 데이터를 LinkedHashSet에 추가할 때는 데이터의 해시 코드를 계산하여 해당 버킷에 저장합니다.
- 동일한 해시 코드를 가진 데이터가 이미 존재하면, 링크드 리스트를 순회하여
중복을 확인하고 추가하지 않습니다. - 데이터의 순서는 linked list에 의해 유지됩니다. 따라서 데이터를 순회할 때에는 링크드 리스트의 연결 구조를 따라가면 됩니다.
LinkedHashSet 이란❓
LinkedHashSet클래스는 데이터의 순서를 유지하면서 중복을 허용하지 않는 자료구조입니다. 이는 해시 테이블과 링크드 리스트를 기반으로 구현되어 있어, 입력된 순서대로 데이터를 저장하고 빠르게 접근할 수 있습니다.
기본 선언
Set<Integer> linkedHashSet = new LinkedHashSet<>();
위와 같이 선언하면 Integer 형태의 데이터를 저장할 수 있는 LinkedHashSet이 생성됩니다. 초기 용량과 로드 팩터(기본 값은 0.75)가 사용됩니다.
초기 용량 지정 선언
Set<String> linkedHashSet = new LinkedHashSet<>(20); // 초기 용량 20으로 설정
위와 같이 선언하면 초기 용량을 지정하여 LinkedHashSet을 생성합니다. 초기 용량은 Set이 저장할 데이터의 예상 개수를 넘어서면 자동으로 조정될 수 있습니다.
로드 팩터 지정 선언
Set<Double> linkedHashSet = new LinkedHashSet<>(10, 0.5f); // 초기 용량 10, 로드 팩터 0.5로 설정
위와 같이 선언하면 초기 용량과 함께 로드 팩터를 지정하여 LinkedHashSet을 생성할 수 있습니다. 로드 팩터는 해시 테이블이 다시 해시코드를 계산하여 데이터를 재분배하는 기준을 나타냅니다.
LinkedHashSet 메서드
add(E e)
LinkedHashSet<Integer> set = new LinkedHashSet<>();
set.add(10);
set.add(20);
set.add(10); // 중복된 요소이므로 추가되지 않음
add() 메서드는 요소를 추가합니다. 이미 존재하는 요소는 추가되지 않습니다.
remove(Object o)
set.remove(20);
remove() 메서드는 지정된 요소를 제거합니다.
contains(Object o)
boolean contains = set.contains(10); // true
contains() 메서드는 지정된 요소가 포함되어 있는지 여부를 반환합니다.
isEmpty()
boolean isEmpty = set.isEmpty(); // false
isEmpty() 메서드는 세트가 비어있는지 여부를 반환합니다.
size()
int size = set.size(); // 1 (중복된 요소가 제거되어서)
size() 메서드는 세트의 요소 수를 반환합니다.
clear()
set.clear();
clear() 메서드는 모든 요소를 제거합니다.
import java.util.LinkedHashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// LinkedHashSet 생성
Set<Integer> set = new LinkedHashSet<>();
// 요소 추가
set.add(10);
set.add(20);
set.add(10); // 중복된 요소이므로 추가되지 않음
// 요소 제거
set.remove(20);
// 요소 순회 및 출력
for (Integer num : set) {
System.out.println(num);
}
// 크기 확인
int size = set.size();
System.out.println("Set size: " + size);
// 요소 포함 여부 확인
boolean contains = set.contains(10);
System.out.println("Contains 10? " + contains);
// 세트 비우기
set.clear();
// 세트가 비어 있는지 확인
boolean isEmpty = set.isEmpty();
System.out.println("Is set empty? " + isEmpty);
}
}
LinkedHashSet 주의사항❗️
import java.util.LinkedHashSet;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
// LinkedHashSet 생성
LinkedHashSet<String> set = new LinkedHashSet<>();
// 요소 추가
set.add("Apple");
set.add("Banana");
set.add("Orange");
// 요소 순회 (향상된 for문 사용)
System.out.println("LinkedHashSet 순회:");
for (String fruit : set) {
System.out.println(fruit);
}
// Iterator를 사용한 순회
Iterator<String> iterator = set.iterator();
System.out.println("Iterator를 사용한 LinkedHashSet 순회:");
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
}
}
LinkedHashSet은 요소의 삽입 순서를 유지하기 때문에, 요소가 삽입된 순서대로 반복문 등을 통해 순회할 수 있습니다.
그러나 직접적으로 인덱스를 사용하여 요소에 접근하는 것은 지원하지 않습니다. 이는 LinkedHashSet이 요소를 해시 테이블에 저장하고, 연결 리스트를 사용하여 순서를 유지하기 때문입니다.
따라서 LinkedHashSet을 사용할 때는 위 코드와 같이 순차적으로 요소를 처리하는 방법을 사용해야 합니다.
LinkedHashSet 장단점
- 장점
- 데이터의 삽입 순서를 유지합니다.
- 중복된 데이터를 자동으로 제거합니다.
- 데이터 접근 및 검색이 빠릅니다.
- 단점
- 내부적으로 추가적인 메모리를 사용하여 순서를 유지하기 때문에 일반적인 HashSet보다 메모리 소모가 큽니다.
- 데이터의 크기가 크거나 입력이 많은 경우, 성능 저하가 발생할 수 있습니다.
정리하자면 LinkedHashSet은 자바에서 데이터를 중복 없이 관리하면서도 순서를 유지하는 데 최적화된 자료구조입니다.
데이터의 순서가 중요한 경우에 사용하여 코드의 가독성과 성능을 유지할 수 있습니다.
다양한 상황에서 유연하게 활용할 수 있으며, 데이터 처리 작업에서 중복 제거와 순서 유지를 한 번에 해결할 수 있습니다.
'자료구조' 카테고리의 다른 글
[자료구조 JAVA] 우선순위 큐(Priority Queue) 클래스 알아보기 ✔ (0) | 2024.06.16 |
---|---|
[자료구조 JAVA] 선형 구조 큐(Queue) 클래스 알아보기 ✔ (0) | 2024.06.15 |
[자료구조 JAVA] 스택 Stack 컬렉션 알아보기 (1/2) (0) | 2024.06.13 |
[JAVA] HashMap 이란 ❓ (1/2) (1) | 2024.06.05 |
[JAVA] ArrayList 알아보기 (동적 배열) (0) | 2024.05.11 |