[Java] List 인터페이스, Stack 클래스

wujin·2023년 5월 5일
0

Java Collection

목록 보기
2/5
post-thumbnail

List 인터페이스

  • List는 Collection의 일부로, 순서가 있는 요소의 집합을 다루기 위해 설계되었다.
  • 중복을 허용한다.
  • 요소의 순서를 보장한다.
  • 구현 클래스
    1. ArrayList<E>
    2. LinkedList<E>
    3. Vector<E>
    4. Stack<E>

List 클래스의 메서드

  • add(E e)
    리스트의 끝에 새로운 요소를 추가

  • get(int index)
    리스트에서 지정된 인덱스의 요소를 반환

  • remove(int index)
    리스트에서 지정된 인덱스의 요소를 제거하고, 제거한 요소를 반환

  • size()
    리스트의 크기를 반환


ArrayList<E> 클래스

ArrayList<E>는 Java에서 제공하는 List 인터페이스를 구현한 클래스 중 가장 많이 사용되는 컬렉션 클래스 중 하나로, 내부적으로 배열을 사용하여 요소들을 저장한다. 요소들을 인덱스로 접근할 수 있으며, 요소의 삽입과 삭제, 크기 변경 등의 기능을 제공한다.

ArrayList<E> 클래스는 배열을 이용하기 때문에 인덱스를 이용해 배열 요소에 빠르게 접근할 수 있습니다. 하지만 배열은 크기를 변경할 수 없는 인스턴스이므로, 크기를 늘리기 위해서는 새로운 배열을 생성하고 기존의 요소들을 옮겨야 하는 복잡한 과정을 거쳐야 한다. ArrayList<E> 클래스는 이 과정을 자동으로 수행하지만, 요소의 추가 및 삭제 작업에 걸리는 시간이 매우 길어지는 단점을 가진다.

ArrayList<E>는 스레드 동기화를 지원하지 않는다. 따라서 동시에 여러 스레드에서 접근할 경우 문제가 발생할 수 있다. 동시에 여러 스레드에서 접근해야 하는 경우에는 Vector<E>CopyOnWriteArrayList<E>를 사용할 수 있다.

예제

import java.util.ArrayList;

public class ArrayListExample {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        // 요소 추가
        list.add("Java");
        list.add("Python");
        list.add("C++");

        // 요소 접근
        System.out.println("list.get(1): " + list.get(1)); // "Python"

        // 요소 수정
        list.set(2, "C#");

        // 요소 삭제
        list.remove(0);

        // 리스트 크기
        System.out.println("list.size(): " + list.size()); // 2

        // 리스트 출력
        System.out.println(list); // ["Python", "C#"]
    }
}

LinkedList<E> 클래스

LinkedList<E>는 Java에서 제공하는 List 인터페이스를 구현한 클래스 중 하나로, ArrayList<E> 클래스가 배열을 이용하여 요소를 저장함으로써 발생하는 단점을 극복하기 위해 고안되었다. LinkedList<E> 클래스는 내부적으로 연결 리스트(linked list)를 이용하여 요소를 저장한다.

배열은 저장된 요소가 순차적으로 저장된다. 하지만 연결 리스트는 저장된 요소가 비순차적으로 분포되며, 이러한 요소들 사이를 링크(link)로 연결하여 구성한다.

다음 요소를 가리키는 참조만을 가지는 연결 리스트를 단일 연결 리스트(singly linked list)라고 한다.

이러한 단일 연결 리스트는 요소의 저장과 삭제 작업이 다음 요소를 가리키는 참조만 변경하면 되므로, 아주 빠르게 처리될 수 있다. 하지만 단일 연결 리스트는 현재 요소에서 이전 요소로 접근하기가 매우 어렵다. 따라서 이전 요소를 가리키는 참조도 가지는 이중 연결 리스트(doubly linked list)가 좀 더 많이 사용된다.

LinkedList<E> 클래스도 위와 같은 이중 연결 리스트를 내부적으로 구현한 것이다. 또한, LinkedList<E> 클래스 역시 List 인터페이스를 구현하므로, ArrayList 클래스와 사용할 수 있는 메소드가 거의 같다.

LinkedList<E> 클래스는 스레드 동기화를 지원한다. 따라서 동시에 여러 스레드에서 접근해도 안전하다.

예제

import java.util.LinkedList;

public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<String>();

        // 요소 추가
        list.add("Java");
        list.add("Python");
        list.add("C++");

        // 요소 접근
        System.out.println("list.get(1): " + list.get(1)); // "Python"

        // 요소 수정
        list.set(2, "C#");

        // 요소 삭제
        list.remove(0);

        // 리스트 크기
        System.out.println("list.size(): " + list.size()); // 2

        // 리스트 출력
        System.out.println(list); // ["Python", "C#"]
    }
}

예제를 보면 ArrayList<E> 클래스의 예제와 거의 동일한 것을 확인할 수 있다. 이처럼 ArrayList<E> 클래스와 LinkedList<E> 클래스의 차이는 사용 방법이 아닌, 내부적으로 요소를 저장하는 방법에 있다.


Vector<E> 클래스

Vector<E> 클래스는 ArrayList<E> 클래스와 같은 동작을 수행하는 클래스이다. 현재의 Vector<E> 클래스는 ArrayList<E> 클래스와 마찬가지로 List 인터페이스를 상속받는다. 따라서 Vector<E> 클래스에서 사용할 수 있는 메소드는 ArrayList<E> 클래스에서 사용할 수 있는 메소드와 거의 같다. 하지만 현재에는 기존 코드와의 호환성을 위해서만 남아있으므로, Vector<E> 클래스보다는 ArrayList<E> 클래스를 사용하는 것이 좋다.


Stack<E> 클래스

Stack<E> 클래스는 List 컬렉션 클래스의 Vector<E> 클래스를 상속받아, 전형적인 스택 메모리 구조의 클래스를 제공한다.

스택 메모리 구조는 선형 메모리 공간에 데이터를 저장하면서 후입선출(LIFO) 의 시멘틱을 따르는 자료 구조이다. 즉, 가장 나중에 저장된(push) 데이터가 가장 먼저 인출(pop)되는 구조이다.

Stack<E> 클래스 메서드

Stack<E> 클래스는 스택 메모리 구조를 표현하기 위해, Vector<E> 클래스의 메서드를 5개만 상속받아 사용한다.

  • boolean empty()
    해당 스택이 비어 있으면 true를, 비어 있지 않으면 false를 반환.

  • E peek()
    해당 스택의 제일 상단에 있는(제일 마지막으로 저장된) 요소를 반환.

  • E pop()
    해당 스택의 제일 상단에 있는(제일 마지막으로 저장된) 요소를 반환하고, 해당 요소를 스택에서 제거.

  • E push(E item)
    해당 스택의 제일 상단에 전달된 요소를 삽입.

  • int search(Object o)
    해당 스택에서 전달된 객체가 존재하는 위치의 인덱스를 반환. 이때 인덱스는 제일 상단에 있는(제일 마지막으로 저장된) 요소의 위치부터 0이 아닌 1부터 시작.

예제

import java.util.Stack;

public class StackExample {
    public static void main(String[] args) {
        // Stack 객체 생성
        Stack<String> stack = new Stack<>();

        // 요소 추가
        stack.push("apple");
        stack.push("banana");
        stack.push("cherry");

        // 요소 접근
        System.out.println(stack.peek()); // 출력: cherry

        // 요소 삭제
        stack.pop();

        // 모든 요소 출력
        while (!stack.isEmpty()) {
            System.out.println(stack.pop());
        }
    }
}

참고 자료
http://www.tcpschool.com/java/java_collectionFramework_list

0개의 댓글