도입
자바에서 데이터를 가장 직관적으로 저장하는 방법을 떠올리면 보통 배열(Array)이나 List가 먼저 생각납니다. 그중 List는 배열보다 훨씬 유연하면서도, 순서와 인덱스라는 개념을 유지할 수 있기 때문에 실무와 알고리즘 문제 양쪽에서 매우 자주 사용됩니다.
예를 들어 게시글 목록, 댓글 목록, 검색 결과, 사용자 입력 순서 보존, 특정 위치의 데이터 조회처럼 “순서대로 저장하고, 필요하면 위치로 접근해야 하는 상황”은 거의 전부 List와 잘 맞습니다.
정의
자바의 List는 java.util.List 인터페이스로 제공되며,
데이터를 순서 있게 저장하고, 각 요소를 인덱스(index)로 접근할 수 있는 구조입니다.
또한 같은 값이 여러 번 들어가도 허용되기 때문에, “중복 값이 자연스러운 데이터”를 관리할 때도 적합합니다. 예를 들어 같은 이름의 사용자가 여러 명 존재하거나, 같은 상품이 장바구니에 여러 번 담길 수 있는 상황은 List가 자연스럽습니다.
- List는 순서를 유지한다.
- List는 중복 저장이 가능하다.
- List는 인덱스로 특정 위치를 조회할 수 있다.
필요성
현실의 많은 데이터는 단순 집합이 아니라 순서를 가집니다. 예를 들어 최근 댓글 목록, 시간순 로그, 정렬된 검색 결과, 사용자의 클릭 흐름은 “어떤 값이 들어 있느냐” 못지않게 “어떤 순서로 들어 있느냐”가 중요합니다.
이때 List는 데이터를 순서대로 유지하고, 필요하면 0번째, 1번째, 마지막 요소처럼 위치 기반으로 꺼낼 수 있기 때문에 매우 자연스럽고 강력한 선택이 됩니다.
- 순서 유지가 자연스럽다.
- 인덱스 조회가 가능하다.
- 중복 데이터를 그대로 보관할 수 있다.
- 배열보다 유연하게 크기를 늘리고 줄일 수 있다.
- 실무와 코딩테스트에서 모두 자주 쓰인다.
배열과 차이
| 항목 | 배열 | List |
|---|---|---|
| 크기 | 고정 | 가변 |
| 순서 | 유지 | 유지 |
| 인덱스 접근 | 가능 | 가능 |
| 삽입/삭제 유연성 | 낮음 | 높음 |
배열은 빠르고 단순하지만 크기가 고정됩니다. 반면 List는 내부적으로 크기 관리가 이루어지기 때문에 데이터 개수가 동적으로 바뀌는 상황에서 훨씬 편리합니다.
기본 사용법
import java.util.ArrayList;
import java.util.List;
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
list.add("apple");
System.out.println(list.get(0)); // apple
System.out.println(list.size()); // 3
list.set(1, "orange");
list.remove(0);
System.out.println(list);
add(value): 맨 뒤에 추가add(index, value): 특정 위치에 삽입get(index): 특정 위치 조회set(index, value): 특정 위치 값 변경remove(index): 특정 위치 삭제remove(value): 특정 값 삭제size(): 원소 개수 반환contains(value): 값 포함 여부 확인
주요 구현체
| 구현체 | 특징 | 추천 상황 |
|---|---|---|
| ArrayList | 배열 기반, 조회 빠름 | 일반적인 대부분의 경우 |
| LinkedList | 연결 구조 기반 | 큐/덱 성격이 강할 때 |
내부적으로 배열을 사용해 데이터를 저장합니다. 인덱스로 접근하는 속도가 매우 빠르기 때문에 가장 널리 사용됩니다. 보통 “특별한 이유가 없으면 ArrayList부터 시작”한다고 생각해도 큰 무리는 없습니다.
각 원소가 다음 원소와 연결되는 구조입니다. 이론적으로는 중간 삽입/삭제에 장점이 있지만, 자바 실무에서는 단순 List 용도보다 Queue / Deque 용도로 더 자주 씁니다.
시간 복잡도
| 연산 | ArrayList | LinkedList |
|---|---|---|
| 맨 뒤 추가 | 보통 O(1) | O(1) |
| 인덱스 조회 | O(1) | O(n) |
| 중간 삽입/삭제 | O(n) | 탐색 포함 시 보통 O(n) |
이론만 보면 LinkedList가 삽입/삭제에 강해 보이지만, 실제로는 “해당 위치까지 가는 비용”이 있기 때문에 일반적인 상황에서는 ArrayList가 더 자주 유리합니다.
순회와 활용
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (String item : list) {
System.out.println(item);
}
순서가 있는 구조이기 때문에, 정렬, 부분 구간 처리, 인덱스 기반 비교, 슬라이딩 윈도우 같은 알고리즘 패턴과도 매우 잘 어울립니다.
실전 사용 예시
- 게시글 목록
- 댓글 목록
- 검색 결과 목록
- 정렬된 점수 리스트
- 입력 순서를 그대로 유지해야 하는 데이터
- 슬라이딩 윈도우, 투 포인터 기반 알고리즘 데이터
주의할 점
- 중간 삽입/삭제 비용이 생각보다 클 수 있다.
remove(int index)와remove(Object value)를 헷갈릴 수 있다.- LinkedList가 이론상 유리해 보여도 실무 기본값은 대개 ArrayList다.
- 원소가 많은데 중간 변경이 잦다면 다른 자료구조도 함께 고려해야 한다.
디버깅
remove(1)이 값 삭제인지 인덱스 삭제인지 의도와 맞는지 본다.요약
- ✅ List는 순서를 유지하고 인덱스로 접근할 수 있다.
- ✅ 중복 데이터 저장이 가능하다.
- ✅ 대표 구현체는 ArrayList와 LinkedList다.
- ✅ 일반적인 기본 선택은 ArrayList다.
- ✅ 순서 있는 목록 데이터에 가장 잘 맞는다.