📌 List란?
- java.util.List는 순서를 유지하면서 값을 저장하는 인터페이스
- 중복 허용 O, 인덱스로 값 접근 가능 (ex. list.get(0) )
- Collection의 자식 인터페이스 중 가장 자주 쓰이는 컬렉션
✅ List를 구현한 주요 클래스
클래스 | 구조 | 특징 | 실무 사용 |
ArrayList | 배열 기반 | 검색 빠름 / 추가,삭제 느림 | 주로 사용 |
LinkedList | 연결 리스트 | 중간 삽입/삭제 빠름 / 검색 느림 | 보통 Queue로 사용 |
Vector | 배열 기반 + 동기화 | 느리고 무거움 | ❌ 사용 지양 |
Stack | Vector 기반 LIFO 구조 | 구식 스택 | ❌ Deque로 대체 권장 |
🛠️ List 선언 방법
import java.util.List;
import java.util.ArrayList;
List<String> list = new ArrayList<>();
//List 인터페이스 , ArrayList 구현체
//List가 부모라면 ArrayList 자식
//List로 선언하면 ArrayList, LinkedList 등 다양하게 선언 가능함( 다형성(polymorphism) )
- 보통 인터페이스 타입(List) 으로 선언하고, 구현체(ArrayList 등) 로 생성해서 사용함 → 확장성과 유연성 좋음
✨List / ArrayList 주요 메서드
메서드 | 설명 | 예시 | 결과 |
add(E) | 리스트 끝에 요소 추가 | list.add("apple") | [apple] |
add(index, E) | 지정 위치에 요소 삽입 | list.add(0, "banana") | [banana, apple] |
get(index) | 인덱스로 요소 조회 | list.get(1) | apple |
set(index, E) | 인덱스의 요소 수정 | list.set(1, "grape") | [banana, grape] |
remove(index) | 인덱스로 요소 제거 | list.remove(0) | [grape] |
remove(Object) | 값으로 요소 제거 | list.remove("grape") | [] |
contains(Object) | 해당 값이 있는지 확인 | list.contains("melon") | true |
indexOf(Object) | 처음 나오는 인덱스 반환 | list.indexOf("melon") | 0 |
lastIndexOf(Object) | 마지막 인덱스 반환 | list.lastIndexOf("melon") | 1 |
size() | 요소 개수 반환 | list.size() | 2 |
isEmpty() | 비어있는지 여부 확인 | list.isEmpty() | false |
clear() | 전체 요소 삭제 | list.clear() | [] |
toArray() | Object[] 로 배열 반환 | list.toArray() | [Object, Object, ...] |
toArray(new String[0]) | 타입 지정 배열로 반환 (타입 안정성 확보) |
list.toArray(new String[0]) | ["melon", "melon"] |
✨ LinkedList 주요 메서드
메서드 | 설명 | 예시 | 결과 |
addFirst(E) | list.addFirst("A") | [A] | 앞에 요소 추가 |
addLast(E) | list.addLast("B") | [A, B] | 뒤에 요소 추가 |
removeFirst() | list.removeFirst() | [B] | 앞 요소 제거 |
removeLast() | list.removeLase() | [] | 뒤 요소 제거 |
peekFirst() | list.peekFirst() | A (삭제 안함) | 앞 요소 확인 |
peekLast() | list.peekLast() | B (삭제 안함) | 뒤 요소 확인 |
pollFirst() | list.pollFirst() | A (삭제함) | 앞 요소 꺼내고 제거 |
pollLast() | list.pollLast() | B (삭제함) | 뒤 요소 꺼내고 제 |
✨ Deque 주요 메서드
메소드 | 설명 | 예시 | 결과 |
offerFirst(E) | 앞에 삽입 (큐 방식) | deque.offerFirst("X") | [X] |
offerLast(E) | 뒤에 삽입 | deque.offerLast("Y") | [X, Y] |
pollFirst() | 앞 요소 꺼냄 | deque.pollFirst() | X (삭제됨) |
pollLast() | 뒤 요소 꺼냄 | deque.pollLast() | Y (삭제됨) |
peekFirst() | 앞 요소 확인 | deque.peekFirst() | X |
peekLast() | 뒤 요소 확 | deque.pookLast() | Y |
📌 List 반복
// 일반 for문
for (int i=0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 향상된 for문 (for-each)
for (String item : list) {
System.out.println(item);
}
// Iterator 사용
Iterator<String> it = list.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
📌 Vector vs Stack
- 같은 구조 기반에서 발전해온 흐름
✅ 흐름 요약
1. Vector (초창기 클래스)
- 배열 기반
- 동기화 O (멀티스레드 안전하지만 느림)
- 현재는 거의 안 씀
2. Stack (Vector의 자식 클래스)
- LIFO(Last In First Out) 구조
- push(), pop() 같은 메서드 추가
- 내부는 여전히 Vector 기반 (무거움)
📌 LinkedList의 Queue vs ArrayDeque의 Queue
항목 | LinkedList의 Queue | ArrayDeque의 Queue |
기능 | Queue 인터페이스 완전 지원 | Queue 인터페이스 완전 지원 |
내부 구조 | 노드 기반 연결 리스트 | 배열 기반 구조 |
쓰임새 | Queue도 되고 List, Deque도 됨 | Queue/Deque에 특화 - 성능 최적화 |
성능 | 조금 느림 (노드 따라가야 함) | 빠름 (배열에서 바로 처리) |
제약 | null 사용 가능 | null 저장하면 NullPointerException |
메모리 | 노드 + 포인터 구조 → 더 무거움 | 배열 구조 → 더 가벼움 |
- 그냥 Queue 용도로만 쓸 거야 - ArrayDeque (가볍고 빠름!)
- Queue + List 기능도 같이 쓰고 싶어 - LinkedList (다기능!)
- null 값으 저장할 수도 있어 - LinkedList (ArrayDeque는 null 저장 안됨)
📌 Deque
- LIFO + FIFO 둘 다 가능 → 양방향 큐
- 빠르고 가벼움
- 대표 구현체: ArrayDeque, LinkedList
Deque<String> stack = new ArrayDeque<>();
stack.push("A"); // 맨 위에 추가
stack.pop(); // 맨 위에서 꺼냄
✅ ArrayList vs LinkedList vs Vector 성능 비교
연산 | ArrayList | LinkedList | Vector |
추가 (맨 끝) | 빠름 | 보통 | 느림 |
추가 (중간) | 느림 | 빠름 | 느림 |
삭제 | 느림 | 빠름 | 느림 |
검색 | 빠름 | 느림 | 보통 |
동기화 | ❌ | ❌ | ⭕ (느림) |
- 검색이 많다 → ArrayList
- 중간 추가/삭제가 많다 → LinkedList
- Vector는 거의 사용 안함
👉 예시
1. ArrayList 예제 - 쇼핑몰 상품 목록
List<String> items = new ArrayList<>();
items.add("신발");
items.add("모자");
System.out.println(items.get(1)); //인덱스 접근이 빠름
- 읽기 빠름, 인덱스로 접근
- 중간에 삽입/삭제하면 느림(배열을 밀어야 하니까)
2. LinkedList 예제 - 채팅 메시지 관리
Queue<String> charQueue = new LinkedList<>();
chatQueue.offer("안녕!");
chatQueue.offer("뭐해?");
System.out.println(chatQueue.poll()); //먼저 들어온 메시지부터 처리
- 앞/중간/뒤 삽입, 삭제 빠름
- 인덱스 접근이 느림(찾아가야 해서)
3. Vector 예제 - 동시성 보장 로그 기록
List<String> logs = new Vector<>();
logs.add("사용자 로그인");
logs.add("결제 성공");
// 멀티스레드 환경에서도 안전하게 add 가능
💡 주로 언제 쓰면 좋을까
- 순서가 중요한 데이터를 저장할 때
- 중복된 값이 허용되는 경우
- 인덱스로 값에 빠르게 접근하고 싶을 때
✅ 실무 상황
상황 | 예시 | 이유 |
데이터 순서를 유지해야 할 때 | 상품 리스트, 주문 내역, 댓글 목록 | 정렬된 순서 그대로 보여줘야 함 |
중복 허용되는 항목 저장 | 장바구니, 최근 본 상품 | 같은 상품 여러 번 담을 수 있음 |
페이지 네이션 처리 | 게시판 10개씩 나눠서 보기 | 인덱스로 접근 (list.get(i)) 유리 |
✅ 코테 / 알고리즘
문제 유형 | 예시 | 이유 |
투 포인터, 슬라이딩 윈도우 | 부분합, 최대 길이 구간 | 빠른 인덱스 접근 가능 (get(i)) |
연속된 값 저장/순회 | 수열, 문자열 나누기 | 순서 유지하면서 순회 용이 |
정답 후보 모으기 | 조건 만족하는 값 저장 | 정렬된 형태로 결과 출력하기 좋음 |
✅ 웹 / 앱 개발
문제 유형 | 예시 | 이유 |
리스트 형태 UI 출력 | 뉴스 목록, 쇼핑몰 상품 리스트 | 데이터 순서 중요 + 중복 허용 |
Form 입력값 관리 | 체크박스, 선택된 태그들 | 선택된 순서대로 처리해야 함 |
비동기 처리 후 결과 수집 | Ajax 응답 모음, 이벤트 로그 저장 | 응답 순서대로 기록됨 |
💡 ArrayList vs LinkedList vs Vector 주로 언제 쓰면 좋을까?
✅ 비교 요약
클래스 | 특징 | 쓰면 좋은 상황 | 예시 |
ArrayList | 배열 기반, 인덱스로 빠르게 접근 가능 | 데이터를 자주 조회할 때 (읽기 위주) | 게시판 목록, 상품 리스트 |
LinkedList | 노드 기반, 중간 삽입/삭제 빠름 | 데이터를 자주 넣고 뺄 때 (변경 위주) | 메신저 채팅 기록, 작업 리스트 |
Vector | ArrayList와 거의 같지만 동기화 처리됨(Thread-safe) | 멀티스레드 환경에서 데이터 안전하게 처리할 때 | 동시성 고려한 로그 수집 |
✅ 상황별 추천 사용 시점
상황 | 추천 클래스 | 이유 |
일반적인 리스트 저장 | ArrayList | 가볍고 빠름, 정렬 순서 유지 |
중간에 자주 삽입/삭제되는 데이터 | LinkedList | 노드 연결 구조라 삽입/삭제 빠름 |
멀티스레드 환경에서 동시에 리스트 접근 | Vector(또는 CopyOnWriteArrayList) | 동기화 되어 있음, 하지만 거의 안씀 |
✅ 코딩테스트/알고리즘 사용 시점
문제 유형 | 추천 클래스 | 이유 |
투 포인터 / 순자 접근 | ArrayList | 인덱스로 빠르게 접근 가능 |
큐 / 스택 구조 문제 | LinkedList | Queue, Deque 로 사용 가능 |
다중 쓰레드 문제 (거의 없음) | Vector(or concurrent 계열) | 실전에서는 거의 등장 안함 |
✅ 앱/웹 개발 사용 시점
기능 | 추천 클래스 | 이유 |
리스트 UI (뉴스, 상품, 댓글) | ArrayList | 순서 중요, 빠른 조회 |
실시간 작업 대기열 | LinkedList | FIFO 구조로 Queue 활용 |
동시성 고려된 데이터 저장 | Vector ❌ → CopyOnWriteArrayList 추천 | Vector는 성능이 너무 낮음 |
✅ 결론
상황 | 추천 |
데이터 조회가 많고 변경이 거의 없음 | ArrayList |
중간 삽입/삭제가 자주 일어남 | LinkedList |
멀티스레드 환경 | Vector (or Collections.synchronizedList) |
FIFO 큐처럼 쓰고 싶다 | Queue<String> q = new LinkedList<>(); |
양쪽에서 넣고 빼고 싶다 | Deque<String> dq = new LinkedList<>(); |
ArrayList는 빠른 검색과 순차 저장에 유리해서, 일반적인 리스트 상황에서는 가장 많이 사용됨
LinkedList는 큐나 덱처럼 동작할 수 있어 중간 삽입/삭제나 스택/큐 구조 구현에 적합
Vector는 멀티스레드 환경에서 동기화를 지원하지만 지금은 거의 사용하지않고, CopyOnWriteArrayList 같은 클래를 추천함
💡인터페이스 vs 구현체
용어 | 의미 | 예 |
인터페이스 | 기능 설계도 | Queue, List, Set, Map |
구현체 | 설계도대로 실제 만든 클래스 | LinkedList, ArrayList, HashSet, HashMap |
'Programming > Java' 카테고리의 다른 글
[Java] 컬렉션(Collection) - Set (0) | 2025.04.18 |
---|---|
[Java] 스레드 (0) | 2025.04.17 |
[Java] 컬렉션(Collection) 프레임워크 (0) | 2025.04.16 |
[Java] Array vs ArrayList vs List (0) | 2025.04.16 |
[Java] 2차원 배열(다차원 배열) (0) | 2025.04.16 |