Java/Java이론

ArrayDeque: 효율적인 양방향 데이터 처리

P_eli 2024. 11. 22. 15:54
728x90
반응형

ArrayDeque 는 Java에서 제공하는 **Deque(이중 끝 큐)**의 구현체 중 하나로, 양쪽 끝에서 삽입과 삭제가 가능하다는 특징을 가지고 있습니다. ArrayDeque는 단순히 스택이나 큐 역할을 넘어, 양방향으로 데이터를 처리할 수 있어 다양한 상황에서 유용하게 활용됩니다. 이번 글에서는 ArrayDeque의 특징, 장점, 주요 메서드, 그리고 실제 활용 사례를 통해 자세히 알아보겠습니다.

 

1. ArrayDeque란?

ArrayDeque는 Deque 인터페이스를 구현한 클래스로, "Array" 기반으로 동작합니다. 이는 내부적으로 배열을 사용해 데이터를 관리하며, 다음과 같은 특징을 갖습니다:

  • 양방향 접근 가능: 앞쪽(addFirst)과 뒤쪽(addLast) 모두에서 삽입과 삭제가 가능.
  • 스택과 큐 모두 지원: 스택의 push/pop 또는 큐의 offer/poll 방식으로 활용 가능.
  • 성능 우수: 크기 제한이 없고 동적 배열 기반이므로, LinkedList 대비 성능이 뛰어남.
  • null 값 허용 안 함: null 요소는 저장할 수 없음.

 

2. ArrayDeque의 장점

  1. 빠른 성능
    ArrayDeque는 배열을 기반으로 구현되어 있어, 삽입 및 삭제 작업이 매우 효율적입니다.
    • ArrayDeque는 큐와 스택의 구현체인 LinkedList보다 메모리 오버헤드가 적고 성능이 더 빠릅니다.
    • 특히 앞뒤로 요소를 추가하거나 제거하는 연산은 상수 시간(O(1)) 안에 수행됩니다.
  2. 유연성
    • 스택: ArrayDeque는 LIFO(Last In, First Out) 방식으로 동작하며, 스택과 동일한 메서드를 제공합니다.
    • : FIFO(First In, First Out) 방식으로도 사용할 수 있어, 일반적인 큐로 활용 가능.
  3. 동적 크기
    • 배열 크기가 자동으로 조정되므로 크기를 명시적으로 지정하지 않아도 됩니다.

 

3. 주요 메서드

1) 삽입

  • addFirst(E e) - 덱의 앞에 요소 추가.
  • addLast(E e) - 덱의 뒤에 요소 추가.
  • offerFirst(E e) / offerLast(E e) - 앞/뒤에 요소 추가, 실패 시 false 반환.

2) 삭제

  • removeFirst() / removeLast() - 앞/뒤 요소 제거. (비어있으면 예외 발생)
  • pollFirst() / pollLast() - 앞/뒤 요소 제거, 비어있으면 null 반환.

3) 조회

  • getFirst() / getLast() - 앞/뒤 요소 확인. (비어있으면 예외 발생)
  • peekFirst() / peekLast() - 앞/뒤 요소 확인, 비어있으면 null 반환.

4) 스택처럼 사용

  • push(E e) - 스택처럼 요소를 위에 삽입.
  • pop() - 스택처럼 맨 위의 요소 제거.

 

4. 사용 예제

예제 1: 기본적인 사용법

import java.util.ArrayDeque;

public class Main {
    public static void main(String[] args) {
        ArrayDeque<String> deque = new ArrayDeque<>();

        // 요소 추가
        deque.addFirst("Start");
        deque.addLast("End");
        deque.addLast("Middle");

        System.out.println("Deque 상태: " + deque);

        // 요소 제거
        String firstElement = deque.removeFirst();
        System.out.println("제거된 첫 번째 요소: " + firstElement);
        System.out.println("Deque 상태: " + deque);

        // 스택처럼 사용
        deque.push("New Start");
        System.out.println("Deque 상태 (스택처럼 추가): " + deque);

        String popped = deque.pop();
        System.out.println("스택에서 제거된 요소: " + popped);
    }
}

 

출력 결과

 

 

예제 2: 웹 브라우저 뒤로/앞으로 가기 기능

import java.util.ArrayDeque;

public class BrowserHistory {
    public static void main(String[] args) {
        ArrayDeque<String> backStack = new ArrayDeque<>();
        ArrayDeque<String> forwardStack = new ArrayDeque<>();

        // 현재 페이지
        String currentPage = "Homepage";

        // 방문
        visitPage("Page1", backStack, forwardStack, currentPage);
        currentPage = "Page1";

        visitPage("Page2", backStack, forwardStack, currentPage);
        currentPage = "Page2";

        // 뒤로 가기
        currentPage = goBack(backStack, forwardStack, currentPage);
        currentPage = goBack(backStack, forwardStack, currentPage);

        // 앞으로 가기
        currentPage = goForward(backStack, forwardStack, currentPage);
    }

    public static void visitPage(String newPage, ArrayDeque<String> backStack, ArrayDeque<String> forwardStack, String currentPage) {
        backStack.push(currentPage);
        forwardStack.clear();
        System.out.println("방문: " + newPage);
    }

    public static String goBack(ArrayDeque<String> backStack, ArrayDeque<String> forwardStack, String currentPage) {
        if (!backStack.isEmpty()) {
            forwardStack.push(currentPage);
            String previousPage = backStack.pop();
            System.out.println("뒤로 가기: " + previousPage);
            return previousPage;
        } else {
            System.out.println("뒤로 갈 페이지가 없습니다.");
            return currentPage;
        }
    }

    public static String goForward(ArrayDeque<String> backStack, ArrayDeque<String> forwardStack, String currentPage) {
        if (!forwardStack.isEmpty()) {
            backStack.push(currentPage);
            String nextPage = forwardStack.pop();
            System.out.println("앞으로 가기: " + nextPage);
            return nextPage;
        } else {
            System.out.println("앞으로 갈 페이지가 없습니다.");
            return currentPage;
        }
    }
}

 

5. ArrayDeque의 활용 사례

  1. 웹 브라우저 뒤로/앞으로 가기: 위 예제처럼, 방문한 페이지를 기록하고 양방향으로 이동하는 로직 구현에 적합.
  2. 양방향 캐싱: 최근 접근된 데이터를 양쪽에서 빠르게 추가/삭제할 수 있음.
  3. 스택과 큐의 대체제: Stack과 LinkedList보다 성능과 메모리 효율이 더 뛰어남.

 

6. 주의사항

  • ArrayDeque는 내부적으로 배열을 사용하므로, 배열 크기가 꽉 찼을 때 새로운 배열로 복사해야 하며 이는 O(n)의 시간이 소요됩니다. 하지만 이는 자동으로 처리되므로 사용자에게 큰 영향을 미치지는 않습니다.
  • 멀티스레드 환경에서는 별도의 동기화가 필요합니다.

 

결론

ArrayDeque는 Java에서 제공하는 효율적이고 다재다능한 자료구조로, 스택과 큐의 기능을 동시에 사용할 수 있는 장점이 있습니다. 간단한 코드로 강력한 기능을 구현할 수 있으므로, 적절한 상황에서 적극적으로 활용해 보세요!

728x90
반응형