Categories: Java

Java 자바 리스트 (List) 정리

List란 무엇인가?

List는 자바 컬렉션 프레임워크의 핵심 인터페이스 중 하나로, 순서가 있는 데이터를 다루는 데 매우 유용한 자료구조입니다. List 인터페이스는 요소의 중복을 허용하며, 인덱스를 기반으로 요소에 접근할 수 있는 특징을 가지고 있습니다. ArrayList와 LinkedList는 List 인터페이스를 구현한 대표적인 클래스들이며, 각각의 장단점을 바탕으로 다양한 상황에 맞는 유연한 데이터 처리를 제공합니다. 이 글에서는 List 인터페이스와 그 주요 구현 클래스들에 대해 자세히 설명하고, 어떻게 각 상황에 맞게 효율적으로 활용할 수 있는지 알려드리겠습니다.

List는 자바의 java.util 패키지에 포함된 인터페이스로, 순서를 유지하면서 중복된 요소를 허용하는 자료구조입니다. List 인터페이스는 인덱스를 사용하여 요소를 관리하고, 이를 통해 빠르게 접근하거나 수정할 수 있도록 설계되어 있습니다. 이러한 구조 덕분에 List는 배열과 유사한 기능을 제공하면서도 배열의 크기 한계를 극복하여 더 유연하게 사용할 수 있습니다.

주요 특징

  • 순서 유지: 요소들이 삽입된 순서가 유지됩니다.
  • 중복 허용: 동일한 값의 요소를 여러 번 추가할 수 있습니다.
  • 인덱스를 통한 접근: 배열과 유사하게 인덱스를 사용하여 요소에 접근하고 수정할 수 있습니다.

List의 주요 구현 클래스

자바에서 List 인터페이스를 구현한 주요 클래스들은 ArrayList, LinkedList, 그리고 Vector 등이 있습니다. 각 클래스는 내부 구조와 특성이 다르기 때문에 상황에 맞는 적절한 선택이 중요합니다.

ArrayList

ArrayList는 동적 배열을 기반으로 구현된 List입니다. 이 클래스는 요소를 추가할 때 내부 배열의 크기가 부족하면 자동으로 배열 크기를 늘리기 때문에 크기 제한 없이 데이터를 추가할 수 있습니다.

  • 빠른 요소 접근: 인덱스를 이용한 요소 접근 속도가 매우 빠르며, 시간 복잡도는 O(1)입니다.
  • 느린 삽입/삭제: 중간에 요소를 삽입하거나 제거할 경우, 요소들의 이동이 필요하므로 최악의 경우 시간 복잡도는 O(n)입니다.
  • 적합한 상황: 요소의 읽기 작업이 빈번한 경우 ArrayList가 적합합니다.
Java
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
Java

LinkedList

LinkedList는 이중 연결 리스트를 기반으로 구현된 List입니다. 각 요소는 노드로 구성되며, 이전 및 다음 요소에 대한 참조를 유지합니다.

  • 빠른 삽입/삭제: 리스트의 중간이나 양 끝에서 요소를 추가하거나 제거하는 작업이 매우 빠릅니다. 시간 복잡도는 O(1)입니다.
  • 느린 요소 접근: 특정 인덱스의 요소에 접근하기 위해 순차적으로 탐색해야 하므로, 시간 복잡도는 O(n)입니다.
  • 적합한 상황: 삽입/삭제 작업이 빈번한 경우 LinkedList가 적합합니다.
Java
List<String> list = new LinkedList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
Java

Vector

Vector는 ArrayList와 유사하지만, 스레드 안전하게 동작하도록 설계되었습니다. Vector의 모든 메서드는 동기화되어 있어 멀티스레드 환경에서 안전하게 사용할 수 있습니다. 하지만 이로 인해 성능이 저하될 수 있습니다.

  • 동기화된 메서드: 모든 메서드가 동기화되어 있어 멀티스레드 환경에서 안전합니다.
  • 성능 문제: 동기화로 인해 단일 스레드 환경에서는 불필요한 오버헤드가 발생할 수 있습니다.
  • 적합한 상황: 멀티스레드 환경에서 데이터의 일관성을 유지해야 하는 경우에 적합합니다.
Java
List<String> list = new Vector<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
Java

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

List 인터페이스는 요소를 관리하기 위한 다양한 메서드를 제공합니다. 다음은 자주 사용되는 주요 메서드들입니다.

요소 추가 (add() 메서드)

요소를 리스트의 끝에 추가합니다.

Java
list.add("Orange");  // 리스트의 끝에 "Orange" 추가
Java

특정 위치에 요소 추가 (add(index, element) 메서드)

특정 인덱스에 요소를 추가합니다. 기존 요소들은 한 칸씩 뒤로 이동합니다.

Java
list.add(1, "Grapes");  // 인덱스 1에 "Grapes" 추가
Java

요소 접근 (get() 메서드)

특정 인덱스의 요소를 가져옵니다.

Java
String fruit = list.get(2);  // 인덱스 2의 요소 가져오기
Java

요소 수정 (set() 메서드)

특정 인덱스의 요소를 수정합니다.

Java
list.set(2, "Peach");  // 인덱스 2의 요소를 "Peach"로 변경
Java

요소 제거 (remove() 메서드)

특정 인덱스의 요소 또는 특정 값을 가진 첫 번째 요소를 제거합니다.

Java
list.remove(1);  // 인덱스 1의 요소 제거
list.remove("Apple");  // "Apple"이라는 값을 가진 첫 번째 요소 제거
Java

리스트 크기 확인 (size() 메서드)

리스트에 포함된 요소의 수를 반환합니다.

Java
int size = list.size();  // 리스트 크기 반환
Java

리스트 비우기 (clear() 메서드)

리스트의 모든 요소를 제거합니다.

Java
list.clear();  // 모든 요소 제거
Java

List의 장단점

장점
  • 유연성: 배열처럼 크기가 고정되지 않고, 필요에 따라 요소를 동적으로 추가 및 제거할 수 있습니다.
  • 다양한 구현체: 상황에 맞는 다양한 구현체(ArrayList, LinkedList 등)를 선택할 수 있어 다양한 요구사항에 대응할 수 있습니다.
단점
  • 성능 이슈: 특정 구현체에 따라 성능 이슈가 발생할 수 있습니다. 예를 들어, LinkedList는 요소 접근 속도가 느리고, ArrayList는 중간 삽입/삭제가 비효율적입니다.
  • 메모리 오버헤드: 연결 리스트 기반의 LinkedList는 노드마다 추가적인 메모리를 사용하기 때문에 배열 기반의 ArrayList보다 메모리 오버헤드가 큽니다.
ArrayList vs LinkedList vs Vector 언제 무엇을 선택할까?
  • ArrayList: 읽기 작업이 많고, 데이터의 삽입/삭제가 적은 경우에 사용하기 좋습니다.
  • LinkedList: 삽입/삭제 작업이 빈번하고, 리스트의 크기가 자주 변경되는 경우에 적합합니다.
  • Vector: 멀티스레드 환경에서 안전한 리스트가 필요할 때 사용합니다. 하지만 단일 스레드 환경에서는 ArrayList를 사용하는 것이 성능 면에서 유리합니다.

List 사용 예제

다음은 List를 사용하여 학생들의 이름을 관리하는 간단한 예제입니다.

Java
import java.util.List;
import java.util.ArrayList;

public class StudentList {
    public static void main(String[] args) {
        List<String> students = new ArrayList<>();
        students.add("Minsu");
        students.add("Jihyun");
        students.add("Soyeon");

        // 학생 목록 출력
        for (String student : students) {
            System.out.println(student);
        }

        // 학생 추가 및 제거
        students.add(1, "Hyejin");
        students.remove("Jihyun");

        // 업데이트된 학생 목록 출력
        System.out.println("\n업데이트된 학생 목록:");
        for (String student : students) {
            System.out.println(student);
        }
    }
}
Java

위 코드에서 List는 학생들의 이름을 동적으로 관리하는 데 사용되며, ArrayList를 구현체로 선택하여 요소를 추가하고 제거하는 작업이 간단하게 이루어집니다.

결론

List는 자바 컬렉션 프레임워크에서 순서가 있는 데이터를 관리할 때 매우 유용한 인터페이스입니다. ArrayList, LinkedList, Vector와 같은 다양한 구현 클래스를 통해 각기 다른 상황에서 효율적으로 데이터를 관리할 수 있습니다. 데이터의 읽기, 삽입, 삭제 패턴에 따라 적절한 구현체를 선택하는 것이 중요하며, 이를 통해 프로그램의 성능을 극대화할 수 있습니다.

이 글을 통해 List 인터페이스와 주요 구현 클래스들의 차이점과 사용 방법을 이해하고, 다양한 상황에서 List를 효과적으로 활용할 수 있기를 바랍니다.

suover

Recent Posts

Spring 스프링 컴포넌트 스캔(Component Scan)이란?

컴포넌트 스캔이란? 컴포넌트 스캔(Component Scan)은 스프링 프레임워크가 특정 패키지를 탐색하면서, 스캔 대상에 해당하는 클래스를 찾아…

2주 ago

Spring 스프링 빈(Bean)이란?

스프링 빈이란? 스프링 빈(Spring Bean)은 스프링 IoC(Inversion of Control) 컨테이너가 관리하는 자바 객체를 의미합니다. 간단히…

3주 ago

Spring 스프링 컨테이너(Spring Container)란?

스프링 컨테이너(Spring Container)란? 스프링 컨테이너는 스프링 프레임워크에서 가장 핵심적인 부분으로, IoC(Inversion of Control) 개념을 기반으로…

1개월 ago

Java 자바 큐(Queue) 개념과 사용법

Queue란 무엇인가? Java에서 Queue는 데이터 구조의 일종으로, 데이터를 선입선출(FIFO, First-In-First-Out) 방식으로 처리합니다. 이 글에서는 Queue의…

1개월 ago

Java 자바 스택(Stack) 개념과 사용법

Stack이란 무엇인가? Java에서 Stack은 자료구조의 한 종류로, 데이터를 순서대로 쌓아 올리는 형태로 운영됩니다. 컴퓨터 과학에서…

2개월 ago

Java 자바 Map – HashMap, TreeMap, LinkedHashMap 정리

소개 자바에서 Map 인터페이스는 키(Key)와 값(Value)의 쌍을 저장하는 자료구조입니다. 이는 연관 배열이라고도 불리며, 각 키는…

2개월 ago