Queue
Java의 Queue 인터페이스는 FIFO(First In First Out) 방식의 순차적 자료 구조를 구현합니다.
즉, 먼저 추가된 요소가 먼저 제거됩니다. Queue 인터페이스는 LinkedList, PriorityQueue, ArrayBlockingQueue 등 다양한 클래스에서 구현됩니다.
Queue 인터페이스는 큐에 요소를 추가, 제거, 검사하는 여러 메서드를 제공합니다. 다음은 가장 일반적으로 사용되는 메서드들입니다.
- add(element): 요소를 큐의 맨 뒤에 추가합니다. 큐가 가득 차 있으면 예외를 발생시킵니다.
- offer(element): 요소를 큐의 맨 뒤에 추가합니다. 큐가 가득 차 있으면 false를 반환합니다.
- remove(): 큐의 앞에서 요소를 제거하고 반환합니다. 큐가 비어 있으면 예외를 발생시킵니다.
- poll(): 큐의 앞에서 요소를 제거하고 반환합니다. 큐가 비어 있으면 null을 반환합니다.
- element(): 큐의 앞에 있는 요소를 제거하지 않고 반환합니다. 큐가 비어 있으면 예외를 발생시킵니다.
- peek(): 큐의 앞에 있는 요소를 제거하지 않고 반환합니다. 큐가 비어 있으면 null을 반환합니다.
PriorityQueue(우선순위 큐)
PriorityQueue 클래스는 Queue 인터페이스의 구현체 중 하나이며, 요소를 우선순위에 따라 정렬하여 저장합니다.
이 우선순위는 요소의 자연스러운 순서(요소가 Comparable 인터페이스를 구현하는 경우) 또는 Comparator에 의해 제공될 수 있습니다. 따라서 PriorityQueue에서는 먼저 추가된 요소가 아닌 가장 높은 우선순위를 가진 요소가 먼저 제거됩니다.
PriorityQueue는 Heap 구현에도 사용할 수 있습니다
다음은 MaxHeap 구현 예제 코드입니다.
import java.util.PriorityQueue;
import java.util.Comparator;
public class Main {
public static void main(String[] args) {
// 최대 힙 생성
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
// 요소 추가
maxHeap.add(4);
maxHeap.add(2);
maxHeap.add(1);
maxHeap.add(3);
// 요소 출력 (힙에서 요소를 제거하면서 출력)
while (!maxHeap.isEmpty()) {
System.out.println(maxHeap.poll());
}
}
}
MinHeap의 경우엔 PriorityQueue<>();로 선언하면 됩니다.
LinkedList
LinkedList는 Collection 프레임워크에서 구현된 클래스로, 기본적으로 Linked List 자료 구조를 구현합니다.
이는 선형 데이터 구조로, 요소들이 연속적인 위치에 저장되지 않고 각 요소는 데이터 부분과 주소 부분을 가진 별도의 객체입니다.
요소들은 포인터와 주소를 사용하여 연결됩니다. 각 요소를 노드라고 합니다.
동적성과 삽입 및 삭제의 용이성 때문에 배열이나 큐보다 선호됩니다.
import java.util.LinkedList;
import java.util.Queue;
public class Main {
public static void main(String[] args) {
Queue<Integer> ll = new LinkedList<>();
// 요소 추가
ll.add(1);
ll.add(2);
ll.add(3);
// 요소 출력 (큐에서 요소를 제거하면서 출력)
while (!ll.isEmpty()) {
System.out.println(ll.poll());
}
}
}
PriorityBlockingQueue
PriorityQueue와 LinkedList 두 구현 모두 스레드 안전(thread-safe)하지 않다는 점을 주의해야 합니다.
스레드 안전한 구현이 필요한 경우, PriorityBlockingQueue는 대안적인 구현 방법입니다.
PriorityBlockingQueue는 PriorityQueue 클래스와 동일한 정렬 규칙을 사용하며,
Java의 concurrent 패키지에 속한 클래스로, 스레드 안전한 PriorityQueue를 제공합니다.
이 클래스는 무제한 크기를 가지며, 스레드가 요소를 검색할 때 해당 요소가 사용 가능해질 때까지 대기하게 할 수 있습니다. 따라서 이 클래스는 동시성을 다루는 멀티스레드 환경에서 유용합니다.
크기가 무제한이기 때문에, 리소스 고갈로 인해 요소 추가가 때때로 실패하며 OutOfMemoryError가 발생할 수 있습니다.
이 클래스를 사용하여 큐 객체를 생성하는 예제 입니다.
import java.util.Queue;
import java.util.concurrent.PriorityBlockingQueue;
public class Main {
public static void main(String[] args) {
Queue<Integer> queue = new PriorityBlockingQueue<>();
// 요소 추가
queue.add(3);
queue.add(1);
queue.add(2);
// 요소 출력 (큐에서 요소를 제거하면서 출력)
while (!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
그렇다면, ArrayList와 LinkedList의 차이는 무엇인가요?
ArrayList | LinkedList | |
구현 | 배열(Array) 사용 | 노드를 연결(linked) |
데이터 접근 시간 | 모든 데이터에 상수 시간 소요 | 위치에 따른 이동 시간 발생 |
삽입/삭제 시간 | 삽입 / 삭제 자체는 상수 시간 | |
삽입 / 삭제 시 데이터 시프트가 필요한 경우 추가 시간 발생 | 삽입 / 삭제 위치에 따라 그 위치까지 이동하는 시간 발생 | |
리스트 크기 확장 | 배열 확장이 필요한 경우 새로운 배열에 복사하는 추가 시간 발생 | 무한대이므로 제한이 없음 |
검색 | 최악의 경우 리스트에 있는 아이템 수 만큼 확인 | |
CPU cache | CPU cache 이점 활용 | 메모리가 연속적이지 않기 때문에 시간적, 공간적 지역성의 캐시 원리를 활용하기 어렵 |
구현 예 | Java의 ArrayList, CPython의 list | Java의 LinkedList |
참고 자료
https://www.geeksforgeeks.org/queue-interface-java/
https://www.youtube.com/watch?v=xvi-n11kym0&t=1083s
'ComputerScience > Java' 카테고리의 다른 글
[Java] immutable(불변) 객체란? (0) | 2024.02.22 |
---|---|
[Java] JUnit5 (0) | 2024.02.22 |
[Java] List와 Set의 차이, 그러면 Set은 어떻게 구현할까요? (0) | 2024.01.29 |
[Java] 인터페이스가 다중 상속이 가능한 이유? (0) | 2024.01.07 |
[Java] abstract vs interface 언제 써야하는가? (2) | 2023.12.07 |