일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- Linux
- 호이스팅
- JPA
- 자바
- DBMS
- group by
- analytics4
- 티스토리챌린지
- 추상클래스
- 오블완
- mssql
- Javascript
- mysql
- java
- rsync
- oracle
- git
- spring
- 차이점
- PostgreSQL
- 리눅스
- SQL
- MariaDB
- Exception
- docker
- 트랜잭션
- IntelliJ
- MongoDB
- 인터페이스
- 명령어
- Today
- Total
hanker
Java - List 인터페이스 (ArrayList, LinkedList, Vector 등) 본문
이번 글에서 List 인터페이스에 대해서 알아보려한다.
List 인터페이스는 여러 구현 클래스를 제공하는데, 해당 구현체들의 특징과 장단점 및 예제를 자세하게 알아보자!
1. List 인터페이스
List는 순서가 있는 데이터를 저장하고, 중복 요소를 허용하는 특징을 가지고 있다.
다양한 구현 클래스를 제공하고, 대표적으로 ArrayList, LinkedList, Vector 가 있다.
1-1. List 특징
- 순서 유지 : 입력된 순서대로 요소가 저장된다.
- 인덱스 접근 가능 : 요소를 index를 사용해 직접 접근 가능
- 중복 허용 : 동일한 값의 요소를 여러 개 저장 가능
1-2. 주요 구현 클래스
클래스 명 | 특징 |
ArrayList | 조회 성능 우수, 삽입/삭제 속도 상대적으로 느림 |
LinkedList | 조회 속도 상대적으로 느림, 삽입/삭제 성능 우수 |
Vector | ArrayList와 유사하지만 동기화(Synchronized) 지원 |
특징 | ArrayList | LinkedList |
데이터 구조 | 동적 배열 | 이중 연결 리스트 |
접근 속도 | 빠름 | 느림 |
삽입/삭제 속도 | 느림 | 빠름 |
메모리 사용량 | 적음 (배열 크기만큼) | 많음 (객체+포인터) |
2. ArrayList
내부적으로 동적 배열을 사용하므로 인덱스 기반 접근이 빠르며, fail-fast iterator(for-each 사용시 데이터 변경되면 에러 발생) 특성을 가지고 있다.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// ArrayList 생성 및 요소 추가
List<String> fruits = new ArrayList<>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Cherry");
// 인덱스를 통한 요소 접근
System.out.println("첫 번째 과일: " + fruits.get(0));
// for-each 문을 이용한 반복
System.out.println("\nfor-each 반복:");
for (String fruit : fruits) {
System.out.println(fruit);
}
// Java 8의 forEach 메서드 활용
System.out.println("\nJava 8 forEach:");
fruits.forEach(System.out::println);
// subList를 이용한 부분 리스트 생성
List<String> subFruits = fruits.subList(1, 3); // 인덱스 1(포함)부터 3(미포함)까지의 요소
System.out.println("\nSubList: " + subFruits);
// fail-fast iterator 예제
System.out.println("\nfail-fast iterator 예제:");
try {
for (String fruit : fruits) {
// 반복 중 직접 리스트를 수정하면 ConcurrentModificationException 발생
if ("Banana".equals(fruit)) {
fruits.add("Orange");
}
}
} catch (Exception e) {
System.out.println("예외 발생: " + e);
}
}
}
- add(), get() 메서드를 사용하여 요소를 추가하고 인덱스로 접근한다.
- subList 사용 : 원본 리스트의 일부를 뷰(View)로 반환하므로, 원본 리스트와 변경 사항이 공유된다.
- fail-fast interator : 반복 중 리스트를 직접 수정하면 ConcurrentModificationException 이 발생함을 보여준다.
2. LinkedList
LinkedList는 내부적으로 이중 연결 리스트(Doubly Linked List)를 사용하여, 삽입/삭제가 빠르지만 랜덤 액세스는 느리다.
import java.util.LinkedList;
import java.util.List;
public class Main {
public static void main(String[] args) {
// LinkedList 생성 및 요소 추가
List<Integer> numbers = new LinkedList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
// LinkedList의 특화 메서드를 사용하려면 타입 캐스팅 필요 (LinkedList로 선언했으면 바로 사용 가능)
LinkedList<Integer> linkedNumbers = (LinkedList<Integer>) numbers;
// 리스트의 앞에 요소 추가
linkedNumbers.addFirst(5);
System.out.println("LinkedList (addFirst): " + linkedNumbers);
// 리스트의 앞/뒤 요소 제거
linkedNumbers.removeFirst();
linkedNumbers.removeLast();
System.out.println("LinkedList (removeFirst & removeLast): " + linkedNumbers);
}
}
- addFirst / removeFirst / removeLast : LinkedList에서는 앞이나 뒤에 요소를 추가 또는 제거할 때 포인터 조작만으로 처리할 수 있다.
- 랜덤 액세스 : LinkedList는 특정 인덱스에 접근할 때 전체를 순회해야 하므로, 대규모 데이터에선 성능 차이가 날 수 있다.
3. Vector
Vector는 ArrayList와 유사하게 동적 배열을 사용하지만, 동기화(synchronized) 처리가 되어 있다.
import java.util.List;
import java.util.Vector;
public class Main {
public static void main(String[] args) {
// Vector 생성 및 요소 추가
List<String> vector = new Vector<>();
vector.add("One");
vector.add("Two");
vector.add("Three");
System.out.println("Vector: " + vector);
}
}
- 동기화 지원 : 멀티스레드 환경에서 사용할 수 있지만, 단일 스레드에서는 오버헤드가 발생할 수 있다.
- 최근에는 Collection.synchronizedList나 CopyOnWriteArrayList를 더 많이 사용한다.
4. CopyOnWriteArrayList
CopyOnWriteArrayList는 읽기 작업이 많은 멀티스레드 환경에서 유용하며, 쓰기에 있어 전체 배열을 복사하는 방식으로 동시성을 보장한다.
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class Main {
public static void main(String[] args) {
List<String> cowList = new CopyOnWriteArrayList<>();
cowList.add("Alpha");
cowList.add("Beta");
cowList.add("Gamma");
// 반복 도중 리스트를 수정해도 ConcurrentModificationException이 발생하지 않습니다.
System.out.println("CopyOnWriteArrayList 반복 및 수정 예제:");
for (String s : cowList) {
System.out.println("현재 값: " + s);
if ("Beta".equals(s)) {
cowList.remove(s); // 안전하게 삭제됨
}
}
System.out.println("수정 후 리스트: " + cowList);
}
}
- 반복중 안전하게 수정 : 일반 ArrayList에서는 반복 중에 수정 시 예외가 발생하지만, CopyOnWriteArrayList는 내부 배열을 복사하여 수정하므로 예외가 발생하지 않는다.
- 쓰기 성능 : 요소를 추가하거나 삭제할 때 전체 배열을 복사하기 때문에, 쓰기 작업이 많은 경우 비효율적이다.
5. subList 사용 시 주의사항
subList는 원본 리스트의 뷰(View)를 반환한다. 따라서 원본 리스트와 subList는 서로의 변경 사항에 영향을 미친다.
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> letters = new ArrayList<>();
letters.add("a");
letters.add("b");
letters.add("c");
letters.add("d");
// 인덱스 1부터 3까지 (b, c) 반환
List<String> subLetters = letters.subList(1, 3);
System.out.println("subList 생성 후: " + subLetters);
// subList를 통한 변경은 원본 리스트에 반영됨
subLetters.set(0, "B");
System.out.println("subList 수정 후 원본 리스트: " + letters);
// 원본 리스트의 구조 변경 후 subList 사용 시 주의!
try {
letters.add("e"); // 구조 변경 발생
// 구조 변경 이후 subList에 접근하면 ConcurrentModificationException이 발생할 수 있음
System.out.println("구조 변경 후 subList: " + subLetters);
} catch (Exception e) {
System.out.println("예외 발생: " + e);
}
}
}
- 뷰(View) 특성 : subList는 원본 리스트의 일부를 참조하기 때문에, subList에 적용된 변경은 원본에도 반영된다.
- 구조 변경 주의 : subList 생성 후 원본 리스트에 구조적 변경(추가, 삭제 등)을 하면 subList에 접근할 때 예외가 발생할 수 있다.
정리
위 예제 코드를 통해서 각 List 구현체의 특성과 주요 메서드 사용법 그리고 주의사항을 알아봤다.
- ArrayList : 빠른 인덱스 접근과 간편한 사용
- LinkedList : 삽입 / 삭제에 유리
- Vector : 동기화가 필요할 때 사용
- CopyOnWriteArrayList : 읽기 위주의 멀티스레드 환경에서 유용
상황에 맞게 적절한 List 구현체와 메서드를 선택하여 보다 효율적이고 안전하게 개발할 수 있다.
끝.
'JAVA' 카테고리의 다른 글
Java - 예외 처리의 활용 및 효율적인 관리 방법 (Custom Exception, Exception Propagation) (0) | 2025.02.10 |
---|---|
Java - 상속과 다형성의 활용 (0) | 2025.02.05 |
JAVA - 멀티스레딩 가이드 (구현부터 동기화까지) (0) | 2025.01.07 |
Java - CheckedException과 UncheckedException이 뭐지? (0) | 2024.12.06 |
Java - 컴파일타임(Compile Time)과 런타임(Run Time)이 뭘까? (0) | 2024.12.05 |