[Java] List
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) | 첫 등장 인덱스, 없으면 -1 | O(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<>()) 또는 도메인에 따라 다른 컬렉션 |
참고
- Object
- Iterable
- Collection
- ArrayList
- LinkedList
- Vector
- CopyOnWriteArrayList
- fail-fast iterator
- ConcurrentModificationException
- Joshua Bloch, Effective Java (3rd ed.), Item 28 (배열보다 리스트)
이 글의 용어 (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…
💬 댓글