• 데이터가 들어오는 위치가 가장 뒤에 있고, 데이터가 나가는 위치가 가장 앞에 있는 자료구조
  • 먼저 들어온 데이터가 가장 먼저 삭제되는 선입선출(First In First Out, FIFO) 자료구조
  • 어떠한 작업 / 데이터를 순서대로 실행/사용하기 위해서 대기시킬 때 사용
  • 큐 응용
    • Queue, PriorityQueue, Deque

코드 설계

  • Queue의 인터페이스의 추상 메서드 확인
  • LinkedList에서 구현 코드 확인
public interface Queue<E> extends Collection<E> {
  boolean add(E paramE);

  boolean offer(E paramE);

  E remove();

  E poll();

  E element(); // 해당 큐의 맨 앞에 있는(제일 먼저 저장된) 요소를 반환

  E peek(); // 해당 큐의 맨 앞에 있는(제일 먼저 저장된) 요소를 반환
}

코드 구현

  • Queue 인터페이스의 핵심 메서드를 LinkedList에서 확인
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, Serializable {
    transient int size = 0;
    transient Node<E> first;
    transient Node<E> last; 
    private static final long serialVersionUID = 876323262645176354L;
    public LinkedList() {}

    // 새로운 Node를 만들어 기존의 Queue의 마지막 node의 next에 연결, Queue의 size + 1
    public boolean add(E paramE) {
        linkLast(paramE);
        return true;
    }
    // add와 같은 기능을 함
    public boolean offer(E paramE) { 
        return add(paramE); 
    }

    // Queue의 index확인 후에 link가 연결된 부분을 null을 대입하여 link 연결을 해제
    public E remove(int paramInt) {
        checkElementIndex(paramInt);
        return unlink(node(paramInt));
    }

    // Queue의 first값을 확인 후 link를 제거한 뒤에 해당 Node를 반환
    public E poll() {
        Node<E> node = this.first;
        return (node == null) ? null : unlinkFirst(node);
    }

    // Queue의 first값을 확인하여 값을 조회
    public E element() { 
        return getFirst(); 
    }

    // Queue의 first값을 확인하여 값을 조회
    public E peek() {
        Node<E> node = this.first;
        return (node == null) ? null : node.item;
    }

    public E getFirst() {
        Node<E> node = this.first;
        if (node == null)
            throw new NoSuchElementException(); 
        return node.item;
    }

    void linkLast(E paramE) {
        Node<E> node1 = this.last;
        Node<E> node2 = new Node<>(node1, paramE, null);
        this.last = node2;
        if (node1 == null) {
            this.first = node2;
        } else {
            node1.next = node2;
        } 
        this.size++;
        this.modCount++;
    }

    E unlink(Node<E> paramNode) {
        E e = paramNode.item;
        Node<E> node1 = paramNode.next;
        Node<E> node2 = paramNode.prev;
        if (node2 == null) {
            this.first = node1;
        } else {
            node2.next = node1;
            paramNode.prev = null;
        } 
        if (node1 == null) {
            this.last = node2;
        } else {
            node1.prev = node2;
            paramNode.next = null;
        } 
        paramNode.item = null;
        this.size--;
        this.modCount++;
        return e;
    }

    private E unlinkFirst(Node<E> paramNode) {
        E e = paramNode.item;
        Node<E> node = paramNode.next;
        paramNode.item = null;
        paramNode.next = null;
        this.first = node;
        if (node == null) {
            this.last = null;
        } else {
            node.prev = null;
        } 
        this.size--;
        this.modCount++;
        return e;
    }

    private void checkElementIndex(int paramInt) {
        if (!isElementIndex(paramInt))
            throw new IndexOutOfBoundsException(outOfBoundsMsg(paramInt)); 
    }
    ...
}

+ Recent posts