Queue(큐)
최근 사용 문서, 인쇄 작업 대기 목록, 버퍼(buffer) 등의 기능을 구현할 때 활용
- 선입선출(FIFO; First In First Out)구조 : 먼저 들어간 데이터를 먼저 꺼내는 구조
Queue의 구현체
Queue는 Queue인터페이스만 있고 별도의 클래스가 없다.
Queue인터페이스를 구현한 클래스들을 사용해야 한다.
LinkedList
PriorityQueue
저장한 순서에 관계없이 우선순위(priority)가 높은 것부터 꺼내게 됨.
null을 저장하면 NullPointerException 발생- 저장공간으로 배열을 사용
- 각 요소를 힙(heap)이라는 자료구조의 형태로 저장
(← 저장된 순서와 실제 우선순위가 다른 이유)
※ 자료구조의 heap과 JVM의 heap은 이름만 같고 다른 것들이다. - 우선순위는 숫자가 작을수록 높다.
- 숫자가 아닌 객체를 저장하려면 각 객체의 크기를 비교할 수 있는 방법을 제공해야 한다.
import java.util.PriorityQueue; import java.util.Queue; public class priorityQueueExample { public static void main(String args[]) { Queue pq = new PriorityQueue(); pq.offer(3); pq.offer(1); pq.offer(10); pq.offer(4); pq.offer(0); System.out.println(pq); Object obj = null; //PriorityQueue에 저장된 요소를 하나씩 꺼낸다. while((obj = pq.poll()) != null) { System.out.println(obj); }} }Output
[0, 1, 10, 4, 3] 0 1 3 4 10저장 순서가 [0, 1, 10, 4, 3]인데도 출력 결과가 0, 1, 3, 4, 10인 것을 확인할 수 있다.
Queue의 변형
Deque(Double-Ended Queue)
양쪽 끝에서 추가/삭제가 가능
Deque의 조상은 Queue- 구현체 : ArrayDequeue, LinkedList
- Stack과 Queue를 하나로 합쳐놓은 것과 같아서 Stack으로 사용할 수도 있고, Queue로 사용할 수도 있다.
import
import java.util.Queue;
import java.util.LinkedList;
선언
방법1
Queue 변수명 = new LinkedList();어떤 자료형이든 삽입, 삭제 가능
Queue에 Integer값과 String값을 모두 넣을 수 있을까?
Queue q = new LinkedList(); System.out.println(q.add(0)); System.out.println(q.add("0"));Output
true true이전에 int형을 넣었어도 String형 삽입 가능
방법2
Queue<자료형>변수명 = new LinkedList<>();자료형에 넣은 자료형만 삽입, 삭제 가능
Queue<Integer>로 생성한 Queue에 Integer값과 String 값을 넣을 수 있을까?
Queue<Integer> q = new LinkedList<>(); System.out.println(q.add(0)); System.out.println(q.add("0"));Output
queueExample.java:10: error: incompatible types: String cannot be converted to Integer System.out.println(q.add("0")); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 errorInteger타입으로 생성한 Queue에 String타입을 넣으려고 하면 에러 발생
Queue
로 생성한 Queue에 Integer값만 넣으면 코드 실행이 잘 될까? Queue<Integer> q = new LinkedList<>(); System.out.println(q.add(0));Output
true생성한 자료형만 추가할 때는 에러 없이 코드가 잘 실행된다.
삽입
boolean
add(Object o)Queue에 객체를 저장
- 성공하면
true를 반환, 저장 공간이 부족하면 IllegalStateException 발생
Queue<Integer>로 생성한 Queue에
add()메서드로 Integer값을 넣어보자Queue<Integer> q = new LinkedList<>(); System.out.println("큐에 값 삽입 성공 : " + q.add(0));Output
큐에 값 삽입 성공 : trueQueue<Integer>로 생성한 Queue에 String값을 넣어보자.
Queue<Integer> q = new LinkedList<>(); System.out.println("큐에 값 삽입 성공 : " + q.add("0"));Output
queueExample.java:9: error: incompatible types: String cannot be converted to Integer System.out.println("큐에 값 삽입 성공 : " + q.add("0")); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 1 error에러가 발생하는 것을 알 수 있다.
- 성공하면
boolean
offer(Object o)Queue에 객체를 저장
- 성공하면
true, 실패하면false를 반환
Queue<Integer>로 생성한 Queue에
add()메서드와offer()메서드로 Integer값을 넣으면 뭐가다를까?Queue<Integer> q = new LinkedList<>(); System.out.println(q.add(0)); System.out.println(q.offer(0));Output
true trueadd()메서드와offer()메서드 모두 차이 없이true를 반환Queue<Integer>로 생성한 Queue에
add()메서드와offer()메서드로 String값을 넣으면 뭐가다를까?Queue<Integer> q = new LinkedList<>(); System.out.println(q.add("0")); System.out.println(q.offer("0"));Output
queueExample.java:9: error: incompatible types: String cannot be converted to Integer System.out.println(q.add("0")); ^ queueExample.java:10: error: incompatible types: String cannot be converted to Integer System.out.println(q.offer("0")); ^ Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output 2 errorsadd()메서드와offer()메서드 모두 차이 없이 에러 발생offer()메서드에서는false를 반환할 줄 알았는데 아니었다.
자료형으로 인한 삽입 실패를 말하는 것이 아니었나보다.
저장공간 부족으로 인한 삽입 실패에서만false를 반환하는 건가?
그것을 확인할 수 있는 코드는 어떻게 써야할까?
- 성공하면
삭제
Object
remove()Queue에서 삭제한 값 반환
※ Queue가 비어있으면 NoSuchElementException 발생비어있지 않은 Queue에서
remove()메서드로 값을 삭제하고 반환되는 값을 출력해 보자Queue<Integer> q = new LinkedList<>(); q.add(0); q.add(10); System.out.println(q.remove()); System.out.println(q.remove());Output
0 10삭제된 값이 출력된다.*(삭제된 값을 반환하는 것을 확인)*
이를 통해 먼저 삽입한 값이 먼저 삭제되는 것을 확인할 수 있다.비어있는 Queue에서
remove()메서드로 값을 삭제하고 반환되는 값을 출력해 보자Queue<Integer> q = new LinkedList<>(); System.out.println(q.remove());Output
Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.LinkedList.removeFirst(LinkedList.java:281) at java.base/java.util.LinkedList.remove(LinkedList.java:696) at queueExample.main(queueExample.java:10)NoSuchElementException 발생
에러랑 Exception은 서로 뜨는 모양이 다르구나❕
Object
remove(Object o)삭제 결과를
boolean타입으로 반환
삭제 성공시,true반환, 삭제 실패시,false반환Queue에 들어있는 값과 들어있지 않는 값을
remove(Object o)로 삭제해 보고 그 반환 값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); System.out.println("Queue에 들어있는 10 삭제 : " + q.remove(10)); System.out.println("Queue에 들어있지 않은 0 삭제 : " + q.remove(0));Output
Queue에 들어있는 10 삭제 : true Queue에 들어있지 않은 0 삭제 : falseQueue에 들어있는 값은
true를 반환, 들어있지 않은 값은false를 반환
Object
poll()Queue에서 삭제한 값 반환
비어있으면 null을 반환
Queue에 여러 값을 삽입 후,
poll()로 값들을 삭제하면서 반환하는 값들을 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); System.out.println(q.poll()); System.out.println(q.poll()); System.out.println(q.poll()); System.out.println(q.poll());Output
10 0 32 null먼저 들어간 값이 먼저 삭제 됨.
Queue가 비어있을 때, 삭제를 하면 null을 반환
Front에 있는 원소 읽기
Object
element()Queue의 맨 앞(front)에 위치한 값(Value) 반환
삭제 없이 요소를 읽어 옴.
※ Queue가 비어있을 때 NoSuchElementException 발생비어있지 않은 Queue에
element()메서드의 반환값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); System.out.println(q.element()); System.out.println(q.element()); System.out.println(q.element());Output
10 10 10값이 삭제되지 않고 제일 먼저 넣은 값(head의 값)이 계속 출력되어 나온다.
비어있는 Queue에
element()메서드의 반환값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); System.out.println(q.element());Output
Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.LinkedList.getFirst(LinkedList.java:255) at java.base/java.util.LinkedList.element(LinkedList.java:674) at queueExample.main(queueExample.java:9)NoSuchElementException 발생
Object
peek()삭제 없이 요소를 읽어 옴.
Queue가 비어있으면
null을 반환비어있지 않은 Queue에
peek()메서드의 반환값을 출력해보고,element()메서드의 반환값과 비교해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); System.out.println("q.peek() = " + q.peek()); System.out.println("q.peek() = " + q.peek()); System.out.println("q.element() = " + q.element());Output
q.peek() = 10 q.peek() = 10 q.element() = 10peek()메서드도element()메서드와 반환값에 차이가 없이
값이 삭제되지 않고 제일 먼저 넣은 값(head의 값)이 출력되어 나온다.비어있는 Queue에
peek()메서드의 반환값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); System.out.println(q.peek());Output
nullelement()메서드와 달리null을 반환
초기화
공백 Queue 만들기
void
clear()반환값 없음
비어있지 않은 Queue에
clear()메서드의 반환값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); System.out.println(q.clear());Output
queueExample.java:13: error: 'void' type not allowed here System.out.println(q.clear()); ^ 1 errorvoid 타입은 출력이 안되는구나❕
비어있지 않은 Queue에
clear()메서드를 사용 후,peek()메서드의 반환값을 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); q.clear(); System.out.println(q.peek());Output
nullQueue가 초기화되어 null이 반환
크기
int
size()현재 Queue에 저장된 객체의 개수를 반환
비어있지 않은 Queue의 크기를 알기 위해
size()메서드를 사용해보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); System.out.println(q.size());Output
3비어있지 않은 Queue를
clear()메서드로 초기화 후,size()메서드를 사용해보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(0); q.add(32); q.clear(); System.out.println(q.size());Output
0초기화 된 Queue의 크기는 0
존재 여부 확인
boolean
contains(Object o)찾는 객체가 존재하면
true반환
찾는 객체가 없으면false반환Queue에 원소를 추가하고
contains()메서드를 사용하여 해당 원소의 존재 여부를 출력해 보고,remove()메서드로 해당 원소를 삭제 후, 다시contains()메서드를 사용하여 해당 원소의 존재 여부를 출력해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); System.out.println("q.contains(10) = " + q.contains(10)); System.out.println("(10 삭제) q.remove(10) = " + q.remove(10)); System.out.println("q.contains(10) = " + q.contains(10));Output
q.contains(10) = true (10 삭제) q.remove(10) = true q.contains(10) = false
공백 Queue 여부 확인
boolean
isEmpty()공백 Queue이면,
true반환
공백 Queue 아니면,false반환비어있지 않은 Queue에서
isEmpty()메서드의 반환값을 출력해 보고, Queue를 초기화 후,isEmpty()메서드로 출력된 반환값과 비교해 보자.Queue<Integer> q = new LinkedList<>(); q.add(10); q.add(1); q.add(-20); System.out.println("q.isEmpty() = " + q.isEmpty()); q.clear(); System.out.println("Queue 초기화 후, q.isEmpty() = " + q.isEmpty());Output
q.isEmpty() = false Queue 초기화 후, q.isEmpty() = true
Queue 메서드 정리
| Throws exception | Returns special value | |
|---|---|---|
| Insert | add(e) | offer(e) |
| Remove | remove() | poll() |
| Examine | element() | peek() |