List란?
순서를 지키고, 중복도 OK! 데이터를 줄 세워서 관리하는 컬렉션
List는 순서가 있는 데이터 집합입니다.
데이터를 입력한 순서대로 저장하고, 중복된 값도 허용해요.
즉, "철수", "영희", "민수"
이렇게 넣으면, 순서대로 [철수, 영희, 민수] 로 저장되고,
같은 값이 들어가도 괜찮아요.
List<String> names = new ArrayList<>();
names.add("철수");
names.add("영희");
names.add("철수"); // 중복 허용!
언제 List를 사용할까요?
- 학생 출석부처럼 순서가 중요한 경우
- 쇼핑몰 장바구니처럼 중복 상품이 들어올 수 있는 경우
- 음악 재생목록처럼 앞뒤 순서대로 처리해야 하는 경우
특징
항목 | 설명 |
순서 유지 | ⭕ |
중복 허용 | ⭕ |
인덱스로 접근 | ⭕ (0번부터 시작) |
대표 구현체 | ArrayList, LinkedList, Vector |
List 구현체종류
List는 인터페이스이고, 실제로는 ArrayList, LinkedList, Vector처럼
구현체(클래스) 를 사용해서 데이터를 저장합니다.
이 세 가지는 모두 순서를 기억하고, 중복을 허용하는 List지만
동작 방식과 성능 특징이 다릅니다.
ArrayList
내부적으로 배열을 사용해 데이터를 저장하는 구조
- 데이터를 인덱스로 빠르게 접근할 수 있어요
- 중간 삽입/삭제는 느림 (배열을 뒤로 밀어야 하니까!)
👉 ArrayList는 자바에서 가장 많이 사용하는 List 구현체입니다.
내부적으로는 배열을 사용해서 데이터를 저장하고,
순서를 유지하면서 중복도 허용해요.
특징
특징 | 설명 |
순서 유지 | 데이터 입력 순서 그대로 유지 |
중복 허용 | 동일한 값 여러 개 저장 가능 |
인덱스 접근 | list.get(0)처럼 인덱스로 바로 접근 가능 |
크기 자동 증가 | 배열 크기를 넘으면 자동으로 더 큰 배열로 복사 |
삽입/삭제 | 느림 (중간 삽입 시 데이터 이동 발생) |
예시
import java.util.ArrayList;
public class ArrayListExample {
public static void main(String[] args) {
ArrayList<String> fruits = new ArrayList<>();
fruits.add("사과");
fruits.add("바나나");
fruits.add("사과"); // 중복 허용
System.out.println(fruits); // [사과, 바나나, 사과]
System.out.println("첫 번째 과일: " + fruits.get(0)); // 사과
System.out.println("총 과일 개수: " + fruits.size()); // 3
}
}
- 출력 결과 -
[사과, 바나나, 사과]
첫 번째 과일: 사과
총 과일 개수: 3
반복문으로 값 꺼내기
for (String fruit : fruits) {
System.out.println(fruit);
}
또는
for (int i = 0; i < fruits.size(); i++) {
System.out.println(fruits.get(i));
}
✅ ArrayList는 인덱스 접근이 빠르기 때문에 반복문과 찰떡궁합입니다!
주요 메서드
메서드 | 설명 |
add(E e) | 요소 추가 |
get(int index) | 요소 꺼내기 |
set(int index, E e) | 특정 위치 값 수정 |
remove(int index) | 요소 삭제 |
size() | 전체 개수 확인 |
contains(E e) | 특정 값 포함 여부 확인 |
단점
- 중간에 데이터를 삽입/삭제하면 배열 요소들을 밀거나 당겨야 하므로 느릴 수 있어요
- 멀티스레드 환경에서는 동기화 처리가 필요해요
👉 이런 상황엔 LinkedList나 CopyOnWriteArrayList 같은 다른 List가 더 적합할 수도 있습니다.
언제 사용할까요?
- 빠른 조회(검색)가 필요한 경우
- 데이터가 자주 수정되지 않는 경우
- 대부분의 일반적인 리스트 처리 상황
- 예: 장바구니, 게시글 목록, 검색 결과 리스트
실무 예시
- 쇼핑몰의 장바구니 목록
- 게시판의 글 목록
- 댓글 리스트
- 검색 결과
요약 정리
- ArrayList는 순서를 유지하면서 데이터를 저장하는 리스트
- 중복을 허용하고, 인덱스로 빠르게 접근 가능
- 대부분의 상황에서 가장 많이 쓰이는 List
LinkedList
노드(node)를 연결해서 데이터를 저장하는 구조
- 삽입/삭제는 빠름 (연결만 바꾸면 됨)
- 대신 인덱스로 접근하는 건 느려요 (처음부터 차례대로 따라가야 함)
👉 LinkedList는 자바에서 제공하는 List의 한 종류로,
데이터를 배열이 아닌 노드(Node) 구조로 연결해서 저장하는 리스트입니다.
즉,
"칸칸이 연결된 데이터 사슬" 같은 구조예요.
각 데이터(노드)는
값(data) 와 다음 노드의 주소(next) 를 가지고 있어요.
특징
특징 | 설명 |
순서 유지 | ⭕ |
중복 허용 | ⭕ |
삽입/삭제 | 빠름 (연결만 바꾸면 됨) |
조회 속도 | 느림 (인덱스 직접 접근 ❌, 앞에서부터 따라가야 함) |
양방향 지원 | LinkedList는 앞/뒤 모두 연결 (Double Linked List) |
예시
import java.util.LinkedList;
public class LinkedListExample {
public static void main(String[] args) {
LinkedList<String> colors = new LinkedList<>();
colors.add("빨강");
colors.add("파랑");
colors.addFirst("노랑"); // 맨 앞에 추가
System.out.println(colors); // [노랑, 빨강, 파랑]
colors.removeLast(); // 마지막 요소 제거
System.out.println(colors); // [노랑, 빨강]
}
}
- 출력 결과 -
[노랑, 빨강, 파랑]
[노랑, 빨강]
반복문으로 꺼내기
for (String color : colors) {
System.out.println(color);
}
System.out.println("첫 번째: " + colors.get(0));
System.out.println("총 개수: " + colors.size());
👉 LinkedList도 get(index)로 값을 꺼낼 수 있어요.
하지만 내부적으로는 배열처럼 바로 꺼내는 게 아니라,
index 0부터 차례대로 따라가면서 찾는 방식이에요.
그래서 get(9999)처럼 인덱스가 클수록 속도가 느려지고 비효율적일 수 있어요
예를 들어, colors.get(9999)를 호출하면
0번부터 9999번까지 하나하나 따라가야 합니다 😵
그래서 데이터 양이 많을 때는 LinkedList에서 인덱스 접근은 비효율적이에요.
주요 메서드
메서드 | 설명 |
addFirst() | 맨 앞에 추가 |
addLast() | 맨 뒤에 추가 |
removeFirst() | 맨 앞 제거 |
removeLast() | 맨 뒤 제거 |
get(int index) | 특정 위치 값 가져오기 |
ArrayList와 뭐가 다를까요?
항목 | ArrayList | LinkedList |
저장 방식 | 배열 기반 | 노드 (연결 리스트) |
중간 삽입/삭제 | 느림 (배열 이동 발생) | 빠름 (노드 연결만 변경) |
인덱스 접근 | 빠름 (O(1)) | 느림 (O(n)) |
메모리 효율 | 상대적으로 좋음 | 연결 정보까지 저장하므로 더 큼 |
언제 사용할까요?
- 중간에 데이터를 자주 추가/삭제해야 할 때
- 맨 앞/뒤에서 자주 꺼내야 할 때
큐(Queue), 덱(Deque), 스택(Stack) 구조처럼 - 데이터 접근보다 변경이 더 빈번한 경우
- 예: 대기열(Queue), 작업 히스토리, Undo 기능
실무 예시
- 브라우저 방문 기록 (뒤로/앞으로 이동)
- 은행 번호표 대기줄
- Undo/Redo 기능
- 실시간 데이터 수신 처리 버퍼
요약 정리
- LinkedList는 데이터를 사슬처럼 연결해 저장하는 리스트
- 중간 삽입/삭제는 빠르지만, 조회는 느릴 수 있어요
- Queue나 Stack처럼 사용할 수 있는 장점도 있어요
Vector
ArrayList처럼 배열 기반이지만, 멀티스레드 환경에서도 안전하게 동작
- ArrayList와 거의 동일한 기능
- 단, 모든 메서드가 synchronized 되어 있어서
동시성(Thread-Safe) 환경에서 안전
👉 Vector는 ArrayList처럼 배열 기반의 리스트입니다.
차이점은 모든 메서드에 동기화(synchronized) 가 되어 있어서,
멀티스레드 환경에서도 안전하게 사용할 수 있다는 것입니다.
특징
특징 | 설명 |
순서 유지 | ⭕ |
중복 허용 | ⭕ |
내부 구조 | 배열 기반 |
점근 속도 | 빠름 (인덱스로 접근 가능) |
삽입/삭제 | 느림 (중간 삽입 시 요소 이동 필요) |
동기화 지원 | ✅ 모든 메서드가 synchronized |
예시
import java.util.Vector;
public class VectorExample {
public static void main(String[] args) {
Vector<String> vector = new Vector<>();
vector.add("A");
vector.add("B");
vector.add("C");
System.out.println(vector); // [A, B, C]
vector.remove(1); // B 제거
System.out.println("B 제거 후: " + vector); // [A, C]
System.out.println("0번 인덱스: " + vector.get(0)); // A
}
}
- 출력 결과 -
[A, B, C]
B 제거 후: [A, C]
0번 인덱스: A
왜 잘 안 쓸까요?
장점은 분명 있습니다.
멀티스레드 환경에서 동기화 처리가 자동되니까 안정적입니다.
하지만 단점도 큽니다
- 모든 메서드에 동기화가 걸려 있어서 단일 쓰레드 환경에서는 느림
- 요즘은 대부분 ArrayList + 필요 시 동기화 방식으로 대체함
Vector 대신 뭘 쓸까요?
요즘에는 이런 방식으로 대체합니다
List<String> threadSafeList = Collections.synchronizedList(new ArrayList<>());
👉 이 방식은 원할 때만 동기화 처리가 가능하고,
성능도 Vector보다 훨씬 유연합니다.
언제 사용할까요?
- 멀티스레드 환경에서 리스트를 동시에 여러 쓰레드가 접근할 때
- 동기화를 수동으로 하지 않고 자동으로 처리하고 싶을 때
- 레거시 코드에서 이미 Vector를 사용하고 있을 때
- 단, 성능상 대부분은 ArrayList + 동기화 처리가 더 많이 사용됨
실무에서는 거의 사용 안 합니다!
과거에는 Vector가 유일한 스레드 안전 리스트였지만,
지금은 더 나은 대안들이 있어요.
실제로는 다음 중 하나를 많이 사용합니다
- ArrayList + Collections.synchronizedList()
➡ 가장 일반적인 대체 - CopyOnWriteArrayList
➡ 동기화와 성능을 모두 고려한 고급 대안 (java.util.concurrent)
요약 정리
- Vector는 ArrayList와 유사하지만,
모든 메서드가 synchronized 되어 있어 멀티스레드에서 안전하게 동작해요. - 하지만 단일 스레드 환경에서는 오히려 느리기 때문에 실무에서는 거의 사용하지 않습니다.
- 요즘은 ArrayList + 동기화 또는 CopyOnWriteArrayList가 더 좋은 선택이에요.
💡 참고로, Vector는 자바에서 사용이 금지된(deprecated) 클래스는 아닙니다.
단지 성능과 구조적인 이유로 요즘에는 실무에서 대체 클래스가 더 선호될 뿐이에요.
유지보수 중인 레거시 시스템에는 아직도 많이 쓰이고 있습니다.
ArrayList, LinkedList, Vector 비교
항목 | ArrayList | LinkedList | Vector |
내부 구조 | 배열 | 연결 리스트 | 배열 |
접근 속도 | 빠름 (O(1)) | 느림 (O(n)) | 빠름 (O(1)) |
삽입/삭제 | 느림 | 빠름 | 느림 |
동기화(멀티스레드) | ❌ | ❌ | ⭕ |
실무 사용 빈도 | ✅ 매우 높음 | ⭕ 조건부 사용 | ❌ 거의 사용 안함 |
어떤 List를 써야 할까요?
- 대부분의 경우 ➡ ArrayList
👉 빠르고 간단해서 실무에서도 가장 자주 사용됨 - 중간 삽입/삭제가 많다면 ➡ LinkedList
👉 연결된 구조라서 삽입/삭제에 유리함 - 멀티스레드 환경이라면 ➡ Collections.synchronizedList(ArrayList) or CopyOnWriteArrayList
👉 Vector은 옛날 방식. 멀티스레드용이지만 요즘은 거의 안 써요.
읽어주셔서 감사합니다 😊
'프로그래밍 언어 > Java' 카테고리의 다른 글
[Java] 38. Set이란? (HashSet, LinkedHashSet, TreeSet) (0) | 2025.04.30 |
---|---|
[Java] 36. 컬렉션 프레임워크란? (0) | 2025.04.22 |
[Java] 35. throw vs throws 차이 완벽 정리 (0) | 2025.04.22 |
[Java] 34. 사용자 정의 예외 만들기 (0) | 2025.04.21 |
[Java] 33. 예외(Exception) 처리 하기 (0) | 2025.04.21 |