Queue는 사전적 의미로는 (무엇을 기다리는 사람, 자동차 등의) 줄 또는 대기 행렬이라는 의미로 흔히 놀이동산 대기줄, 게임에서 '큐가 안잡혀요' 할 때 큐. 정도 생각하면 될 것이다.
여기서 비유를 든 예시를 잘 살펴보면, 모두 먼저온 사람이 먼저 (게임 혹은 놀이기구) 사용하는 것을 알 수 있다.
즉, Queue는 먼저 들어온 데이터를 우선 처리하는 자료구조이다.(FIFO - Firtst In First Out)
※반례로 stack은 LIFO(Last In First Out)구조로 늦게 들어온 데이터를 우선 처리
- 큐는 먼저 들어온 데이터를 먼저 처리하는 자료구조로 FIFO(First In First Out) 구조를 가진다.
- 두 개의 입출력 방향을 가지는 데, 데이터가 들어오는 방향과 나가는 방향이 다르다
- ※ stack은 단 방향으로 들어오는 방향이 곧 나가는 방향과 일치
- 큐는 Front(프론트), rear(리어) 라는 이름으로 각 끝을 지정해
Front는 삭제 연산을, rear는 삽입 연산만 수행
큐를 사용하는 사례에는 프린터 인쇄 과정이 있다.
문서를 작성한 후 출력을 하게 되면 해당 문서는 인쇄 작업(임시 기억 장치의) Queue에 들어감
프린터기는 인쇄 작업 Queue에 들어온 순서대로 출력
해당 사례처럼 컴퓨터 장비들 사이에서 데이터를 전송할 때 Buffer를 사용하는 데,
이때 Queue가 Buffer처럼 수행할 수 있다.
이를 좀 더 설명해보자면,
Buffer는 데이터가 임시로 저장되는 임시 메모리 영역으로 데이터를 다른 곳으로 전송할 때 사용되는데, 이때 데이터의 속도가 다르거나 처리량이 다른 장비들 간의 데이터 전송을 조절할 때 사용된다.
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
대게 Java에서 Queue를 사용할 때는 LinkedList로 많이 구현한다.
하지만, Queue 인터페이스를 구현하는 ArrayDeque나 PriorityQueue도 상황에 맞게 사용한다.
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
queue.offer("box1"); // queue에 값 box1를 추가
//or
queue.add("box2"); // queue에 값 box2를 추가
크기가 5인 큐에 현재 box1
과 box2
가 추가된 모습
큐는 선형 자료구조로, 해당 그림과 같이 되어있으며 큐는 양방향 입출 구조로 되어 있어
삽입되는 방향과 삭제되는 방향이 서로 다릅니다.
Type | method | 설명 |
---|---|---|
boolean | add(E e) | 용량제한을 위반하지 않고 즉시 수행할 수 있는 경우 해당 요소를 큐에 삽입, |
성공시 True, 사용할 수 있는 공간이 없을 경우 IllegalStateException 반환 | ||
boolean | offer(E e) | 용량제한을 위반하지 않고 즉시 수행할 수 있는 경우 해당 요소를 큐에 삽입, |
성공 시 True, 실패시 False를 반환한다. |
여기서 용량제한 위반이란??
violating capacity restrictions로, 한계 용량 제한을 위반하는 것을 말합니다.
즉, 큐가 최대 용량에 도달해 요소를 추가하지 못하는 상황큐는 특정한 용량을 가지고 있고 이 용량이 곧 큐가 저장할 수 있는 요소의 최대 개수를 의미합니다.
만약 최대 개수에 도달하였는데, 요소를 추가한다면 위의 add() 메서드 처럼 IllegalStateException이 발생할 수 있는 것입니다.만약 크기가 5인 큐가 있다고 가정하면, 이미 5만큼 차있는 큐에 요소를 추가하게 되면 용량제한 위반으로 요소를 추가할 수 없는 상황이 될 수 있는 것입니다.
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
queue.offer("box1"); // queue에 값 box1를 추가
//or
queue.add("box2"); // queue에 값 box2를 추가
System.out.println(queue.poll()); // box1 출력(맨 앞 요소)
System.out.println(queue.remove()); // box2 출력(box1이 제건 된 다음 앞 요소)
System.out.println(queue); // [] 출력(빈 배열)
type | method | 설명 |
---|---|---|
Element | poll() | 큐에서 현재 첫번째 값을 제거한 후 해당 값을 반환하며, 큐가 비어있을 경우 null을 반환 |
Element | remove() | 큐에서 현재 첫번째 값을 제거한 후 해당 값을 반환 |
단, 큐가 비어있을 경우 NoSuchElementException 예외 처리 | ||
Void | clear() | 큐 안에 있는 모든 요소를 제거 |
여기서 문제가 존재한다. 바로 Queue인터페이스에는 clear() 메서드가 존재하지 않기 때문에 위와 같이 LinkedList를 Queue로 타입 캐스팅하여 사용하게 되는 경우 사용할 수 없다.
LinkedList를 객체로 만들었지만, 타입 캐스팅을 Queue로 한다면, Queue에 존재하는 메서드만 사용할 수 있기 때문 그렇다면 어떻게 하면 clear()메서드를 사용할 수 있는가?
LinkedList<String> queue = new LinkedList<>(); //이걸로 선언하면 된다.
import java.util.LinkedList;
import java.util.Queue;
Queue<String> queue = new LinkedList<>();
queue.offer("box1"); // queue에 값 box1를 추가
//or
queue.add("box2"); // queue에 값 box2를 추가
System.out.println(queue.peek()); // box1 출력(맨 앞 요소)
System.out.println(queue.element()); // box1 출력(맨 앞 요소_
System.out.println(queue); // [box1, box2] 출력(빈 배열)
//만약 여기 빈 큐에 peek()와 element()를 사용하게 될 시
Queue<String> queue2 = new LinkedList<>();
System.out.println(queue2.peek()); // null 출력
System.out.println(queue2.element()); // NoSuchElementException 출력
type | method | 설명 |
---|---|---|
Element | peek() | 큐에서 현재 첫번째 값을 제거하지 않고 반환하며, 큐가 비어있을 경우 null을 반환 |
Element | element() | 큐에서 현재 첫번째 값을 제거하지 않고 반환하며, |
단, 큐가 비어있을 경우 NoSuchElementException 예외 처리 |
즉, 이를 정리한다면 아래와 같이 정리할 수 있겠다.
예외 발생 | 값 반환 | |
---|---|---|
요소 추가 | add(E e) | offer(E e) |
요소 삭제 | remove() | poll() |
요소 검색 | element() | peek() |