본문 바로가기
자바/자바 자료구조

자바 - Deque 이야기

by 신재은👩🏼‍💻 2024. 4. 27.

자바에서 쓸 수 있는 자료구조 클래스에 대한 이야기가 거의 끝을 향해 가고 있다.

덱하고 셋만 하면 끝이다!

힘을 내어 빨리 끝을 내 보자!

 

Java에서 Deque 인터페이스는 "double ended queue"의 약자로, 양쪽 끝에서 요소를 추가하거나 제거할 수 있는 선형 컬렉션입니다. 이는 스택(stack)과 큐(queue)의 일반화된 형태로 볼 수 있으며, FIFO(First-In-First-Out) 및 LIFO(Last-In-First-Out) 양쪽의 동작을 모두 지원합니다.

https://www.geeksforgeeks.org/deque-interface-java-example/

 

다른 포스트에서 여러 번 나왔지만 한 번 더 넣었다.

https://www.youtube.com/watch?app=desktop&v=q_pW6VwNkpU

 

덱에 대해 더 딥하게 알아야 할 내용이 있나...?

LinkedList 같은 경우는 진짜 머리 빠게지게까지 볼 수 있는데 덱에서는 그러지 말자... 호호호... 😃...

Deque 인터페이스의 주요 메서드

요소 추가

  • addFirst(E e) / offerFirst(E e): 덱의 앞쪽에 요소를 추가합니다. offerFirst는 추가가 불가능할 때 false를 반환합니다.
  • addLast(E e) / offerLast(E e): 덱의 뒤쪽에 요소를 추가합니다. offerLast는 추가가 불가능할 때 false를 반환합니다.

요소 제거

  • removeFirst() / pollFirst(): 덱의 앞쪽에서 요소를 제거하고 그 값을 반환합니다. pollFirst는 덱이 비어 있을 때 null을 반환합니다.
  • removeLast() / pollLast(): 덱의 뒤쪽에서 요소를 제거하고 그 값을 반환합니다. pollLast는 덱이 비어 있을 때 null을 반환합니다.

요소 검색

  • getFirst() / peekFirst(): 덱의 첫 번째 요소를 반환하지만 제거하지는 않습니다. peekFirst는 덱이 비어 있을 때 null을 반환합니다.
  • getLast() / peekLast(): 덱의 마지막 요소를 반환하지만 제거하지는 않습니다. peekLast는 덱이 비어 있을 때 null을 반환합니다.

요소 존재 여부 검사

  • contains(Object o): 덱에 특정 요소가 포함되어 있는지 여부를 확인합니다.

크기 및 상태 정보

  • size(): 덱에 있는 요소의 개수를 반환합니다.
  • isEmpty(): 덱이 비어 있는지 여부를 반환합니다.

요소 제거

  • clear(): 덱의 모든 요소를 제거합니다.

요소 순회

  • iterator(): 덱의 요소를 순회할 수 있는 Iterator를 반환합니다.
  • descendingIterator(): 덱을 역순으로 순회할 수 있는 Iterator를 반환합니다.

add, remove는 덱이 다 차 있거나 요소가 없어서 기능할 수 없으면 예외를 던진다.

그렇다 해도 add, remove / offer, poll이 굳이 두 쌍 있는 게 이해가 안 되지 않는가?

사용 시나리오

  • addFirst()는 용량 제한이 없는 Deque 구현체, 예를 들어 LinkedList에서 사용할 때 적절합니다. 요소 추가가 실패할 것으로 예상하지 않는 상황에서 사용할 수 있습니다. <- 예외 처리 할 필요가 없을 때 쓴다.
  • offerFirst()는 용량 제한이 있는 경우나 실패할 가능성을 고려해야 할 때 사용하며, 실패했을 때 예외 처리를 하지 않아도 되는 경우에 유용합니다. <- true, false로 기능 적용 여부를 알아야 할 때 쓴다.

비슷하게 add()와 offer(), remove()와 poll() 메서드 쌍 사이에도 같은 차이가 있습니다. add()와 remove()는 성공하지 못했을 때 예외를 던지고, offer()와 poll()은 특정 조건에서 실패하더라도 예외를 던지지 않고 false 또는 null을 반환합니다. 이러한 차이점은 메서드 사용 시 예외 처리를 할지, 아니면 메서드 호출의 반환값으로 성공 여부를 확인할지를 결정할 때 중요합니다.

Deque 인터페이스의 구현체

Java에서 Deque 인터페이스는 여러 클래스에 의해 구현됩니다. 가장 일반적인 구현체는 다음과 같습니다:

  • ArrayDeque: 배열 기반의 덱 구현체로, 내부적으로 동적 배열을 사용하여 요소를 저장합니다.
  • LinkedList: 연결 리스트 기반의 덱 구현체로, 내부적으로 이중 연결 리스트를 사용하여 요소를 저장합니다.

각 구현체는 상황에 따라 다른 성능 특성을 가지고 있습니다. 예를 들어, ArrayDeque는 일반적으로 LinkedList보다 메모리 사용이 더 효율적이며, 빠른 임의 접근을 제공합니다. 반면에, LinkedList는 요소의 삽입 및 제거가 빈번하게 일어나는 경우 좋은 선택일 수 있습니다.

import java.util.Deque;
import java.util.LinkedList;

public class Example {
    public static void main(String[] args) {
        Deque<Integer> deque = new LinkedList<>();

        deque.offerFirst(1);  // Deque: [1]
        deque.offerLast(2);   // Deque: [1, 2]
        deque.offerFirst(3);  // Deque: [3, 1, 2]
        deque.offerLast(4);   // Deque: [3, 1, 2, 4]

        System.out.println(deque.pollFirst());  // Output: 3, Deque: [1, 2, 4]
        System.out.println(deque.pollLast());   // Output: 4, Deque: [1, 2]
        
        System.out.println(deque.peekFirst());  // Output: 1
        System.out.println(deque.peekLast());   // Output: 2
    }
}

 

이 예제에서 Deque는 스택과 큐의 기능을 모두 사용하여 요소를 관리합니다. 이처럼 덱은 매우 유연한 자료구조로, 다양한 시나리오에서 유용하게 사용될 수 있습니다.


덱은 더 이상 안 봐도 될 것 같다.

바로 문제 풀러 가자!