본문으로 건너뛰기
김신건의 로그

[Java] List

· 수정 · 📖 약 2분 · 660자/단어 #java #collection #data-structure #list #interface
List, java.util.List, Java List, JList, 리스트, List interface

정의

java.util.List순서가 있고 중복이 허용 되는 컬렉션을 표현하는 인터페이스. 각 원소는 0 부터 시작하는 정수 인덱스로 접근 가능.

Collection 인터페이스를 확장하며, Iterable 의 모든 성질을 물려받는다. 대표 구현체로 ArrayList, LinkedList, Vector, CopyOnWriteArrayList 가 있다.

시각화

핵심 메서드

메서드의미일반적 비용
get(int i)i 번째 원소 반환구현체 의존
set(int i, E e)i 번째 원소를 e 로 교체, 이전 값 반환구현체 의존
add(E e)끝에 추가, true 반환보통 O(1)
add(int i, E e)i 위치에 삽입구현체 의존
remove(int i)i 번째 원소 삭제, 그 값 반환구현체 의존
remove(Object o)첫 번째로 발견된 o 삭제O(n)
indexOf(Object o)첫 등장 인덱스, 없으면 -1O(n)
size()원소 개수O(1)
iterator(), listIterator()순회O(1) 생성
subList(int from, int to)부분 뷰 (백킹 리스트 공유)O(1)

구현체별 특징 한눈에

구현체내부 구조random access끝에 add앞/중간 삽입thread-safe
ArrayList동적 배열O(1)amortized O(1)O(n)
LinkedList양방향 연결 리스트O(n)O(1)O(1) (노드 있을 때) / O(n) (인덱스)
Vector동적 배열 + 메서드 동기화O(1)amortized O(1)O(n)✓ (메서드 단위)
CopyOnWriteArrayList불변 배열 + 쓰기 시 복사O(1)O(n) (전체 복사)O(n)

IMPORTANT

거의 모든 실무 코드에서 ArrayList 가 기본 선택. LinkedList 가 더 빠를 것 같은 상황 (앞 삽입) 도 실측하면 ArrayList 가 빠를 때가 많다. 캐시 친화성 차이 때문.

기본 사용

List<String> users = new ArrayList<>();
users.add("Alice");                    // [Alice]
users.add("Bob");                      // [Alice, Bob]
users.add(0, "Charlie");               // [Charlie, Alice, Bob]
users.set(1, "Dave");                  // [Charlie, Dave, Bob]
String first = users.get(0);           // "Charlie"
boolean has = users.contains("Bob");   // true
users.remove("Charlie");               // [Dave, Bob]

for (String u : users) {               // for-each (iterator)
    System.out.println(u);
}

불변 (Immutable) List

Java 9 부터 List.of(...) 정적 메서드가 추가됐다.

List<Integer> primes = List.of(2, 3, 5, 7, 11);
primes.add(13);  // UnsupportedOperationException

List.copyOf(other) 로 기존 리스트의 불변 복사본도 가능.

fail-fast 와 동시 수정

ArrayList, LinkedList, Vector 의 iterator 는 순회 중 구조가 변경되면 ConcurrentModificationException 을 던진다 (fail-fast iterator). 단일 스레드 안에서도 발생한다.

List<Integer> list = new ArrayList<>(List.of(1, 2, 3, 4));
for (Integer x : list) {
    if (x % 2 == 0) list.remove(x);  // ❌ ConcurrentModificationException
}

// ✅ Iterator.remove() 만 안전
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    if (it.next() % 2 == 0) it.remove();
}

// ✅ Java 8+: removeIf
list.removeIf(x -> x % 2 == 0);

CopyOnWriteArrayList 만 예외, snapshot iterator 라 CME 가 발생하지 않는다.

어떤 구현체를 골라야 하나

상황권장
기본, 의심스러우면ArrayList
앞/뒤 빈번 삽입·삭제, Deque 로도 쓰고 싶다LinkedList (단, 인덱스 접근 거의 없을 때)
레거시 코드 호환Vector (새 코드에서는 피한다)
읽기 多 / 쓰기 거의 없음, 동시성CopyOnWriteArrayList
불변 데이터List.of(...), List.copyOf(...)
일반적 동시성Collections.synchronizedList(new ArrayList<>()) 또는 도메인에 따라 다른 컬렉션

참고

이 글의 용어 (9개)
[Java] ArrayListjava
정의 는 동적 배열 (dynamic array) 로 구현된 . 내부적으로 를 들고 다니며, 용량이 부족해지면 새 배열로 옮긴다. Java 의 가장 흔한 컬렉션 구현체. 인덱스 기…
[Java] Collectionjava
정의 는 그룹으로 묶인 객체들을 표현하는 최상위 인터페이스. JCF (Java Collections Framework) 의 입구이자, / / / 모두 이를 확장한다. 자체는 직접…
[Java] ConcurrentModificationExceptionjava
정의 (CME) 는 가 컬렉션의 구조 변경을 탐지했을 때 던지는 unchecked 예외 ( ). 이름과 달리 반드시 동시성 (멀티스레드) 문제일 때만 발생하는 것이 아니다. 단일…
[Java] CopyOnWriteArrayListjava
정의 는 쓰기 시 배열 전체를 복사 하는 thread-safe 구현. 읽기에는 lock 이 전혀 없고, 쓰기에는 으로 직렬화한다. (JSR-166) 의 컬렉션. 읽기 압도적 다,…
[Java] Fail-Fast Iteratorjava
정의 Fail-Fast Iterator 는 순회 도중 컬렉션의 구조가 변경되면 즉시 을 던지는 iterator. , , 등 대부분의 컬렉션의 iterator 가 이 방식. 목적은…
[Java] Iterablejava
정의 는 루프로 순회 가능한 모든 타입의 최상위 인터페이스. 단 하나의 추상 메서드, 를 정의한다. 인터페이스가 을 extends 하므로 , , , 등 모든 컬렉션이 자동으로 대…
[Java] LinkedListjava
정의 는 양방향 연결 리스트 (doubly linked list) 로 구현된 이자 . 각 원소는 와 포인터를 가진 노드로 보관된다. 와 같은 List 이지만, 메모리 레이아웃과 …
[Java] Objectjava
정의 는 Java 의 모든 클래스의 최상위 부모 (root) 클래스. 가 명시되지 않은 클래스는 컴파일러가 자동으로 를 붙인다. 인터페이스는 클래스가 아니라 를 직접 상속하지는 …
Geometry Basic: 벡터, CCW, 외적, 내적algorithm
정의 기하 알고리즘의 밑바탕. 대부분의 2D/3D 기하 문제는 벡터 연산, 내적/외적, CCW 판정 세 가지의 조합으로 풀립니다. 벡터 2D 벡터: 두 점 $A = (ax, ay…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기