Java LinkedList 완벽 가이드: 예제와 함께하는 핵심 기능
Java LinkedList
Java 컬렉션 프레임워크의 LinkedList를 활용한 효율적인 데이터 조작법을 실전 코드 예제와 모범 사례와 함께 살펴봅니다.
LinkedList 클래스는 이중 연결 리스트를 구현합니다. 각 요소(노드)는 세 필드를 가집니다:
- prev – 이전 노드 참조(첫 요소는 null)
- next – 다음 노드 참조(마지막 요소는 null)
- data – 노드에 저장된 실제 값
Java LinkedList 생성하기
특정 요소 타입으로 LinkedList를 인스턴스화하세요:
LinkedList<Type> list = new LinkedList<>();
예제:
// Integer 리스트
LinkedList<Integer> numbers = new LinkedList<>();
// String 리스트
LinkedList<String> words = new LinkedList<>();
예제: Java에서 LinkedList 생성
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> animals = new LinkedList<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
System.out.println("LinkedList: " + animals);
}
}
출력
LinkedList: [Dog, Cat, Cow]
이 코드는 add()로 세 요소를 채운 기본 animals LinkedList를 보여줍니다.
Java LinkedList 동작 원리
배열과 달리 노드들은 메모리에 분산되어 링크로 연결됩니다. 아래 다이어그램은 세 노드와 연결을 보여줍니다.
- Dog – 첫 노드, prev = null, next = Cat
- Cat – 중간 노드, prev = Dog, next = Cow
- Cow – 마지막 노드, prev = Cat, next = null
더 깊은 이해를 위해 Linked List 문서를 참조하세요.
주요 LinkedList 메서드
가장 자주 사용되는 연산들:
1. 요소 추가하기
add()로 노드 추가, 인덱스 지정 가능:
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> animals = new LinkedList<>();
animals.add("Dog");
animals.add("Cat");
animals.add("Cow");
System.out.println("LinkedList: " + animals);
animals.add(1, "Horse");
System.out.println("Updated LinkedList: " + animals);
}
}
출력
LinkedList: [Dog, Cat, Cow] Updated LinkedList: [Dog, Horse, Cat, Cow]
두 번째 add()가 인덱스 1에 "Horse"를 삽입하여 이후 요소들을 이동시킵니다.
2. 요소 접근하기
get()으로 인덱스별 조회:
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> languages = new LinkedList<>();
languages.add("Python");
languages.add("Java");
languages.add("JavaScript");
System.out.println("LinkedList: " + languages);
String str = languages.get(1);
System.out.print("Element at index 1: " + str);
}
}
출력
LinkedList: [Python, Java, JavaScript] Element at index 1: Java
iterator()나 listIterator()로 고급 순회도 가능합니다.
3. 요소 수정하기
set()으로 특정 인덱스 요소 교체:
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> languages = new LinkedList<>();
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
languages.add("Java");
System.out.println("LinkedList: " + languages);
languages.set(3, "Kotlin");
System.out.println("Updated LinkedList: " + languages);
}
}
출력
LinkedList: [Java, Python, JavaScript, Java] Updated LinkedList: [Java, Python, JavaScript, Kotlin]
4. 요소 제거하기
remove()로 인덱스별 삭제:
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> languages = new LinkedList<>();
languages.add("Java");
languages.add("Python");
languages.add("JavaScript");
languages.add("Kotlin");
System.out.println("LinkedList: " + languages);
String removed = languages.remove(1);
System.out.println("Removed Element: " + removed);
System.out.println("Updated LinkedList: " + languages);
}
}
출력
LinkedList: [Java, Python, JavaScript, Kotlin] Removed Element: Python New LinkedList: [Java, JavaScript, Kotlin]
기타 유용한 메서드
| 메서드 | 설명 |
contains() | 값 존재 여부 확인 |
indexOf() | 첫 번째 출현 인덱스 |
lastIndexOf() | 마지막 출현 인덱스 |
clear() | 모든 요소 제거 |
iterator() | Iterator 제공 |
LinkedList를 Queue와 Deque로 사용하기
LinkedList는 Queue와 Deque를 구현하므로 FIFO와 LIFO 연산을 지원합니다. 주요 메서드:
| 메서드 | 설명 |
addFirst() | 머리에 추가 |
addLast() | 꼬리에 추가 |
getFirst() | 머리 조회 |
getLast() | 꼬리 조회 |
removeFirst() | 머리 제거 |
removeLast() | 꼬리 제거 |
peek() | 제거 없이 머리 조회 |
poll() | 머리 조회 및 제거 |
offer() | 꼬리에 인큐 |
예제: LinkedList를 Queue로 사용
import java.util.LinkedList;
import java.util.Queue;
class Main {
public static void main(String[] args){
Queue<String> languages = new LinkedList<>();
languages.add("Python");
languages.add("Java");
languages.add("C");
System.out.println("LinkedList: " + languages);
String first = languages.peek();
System.out.println("Accessed Element: " + first);
String removed = languages.poll();
System.out.println("Removed Element: " + removed);
System.out.println("LinkedList after poll(): " + languages);
languages.offer("Swift");
System.out.println("LinkedList after offer(): " + languages);
}
}
출력
LinkedList: [Python, Java, C] Accessed Element: Python Removed Element: Python LinkedList after poll(): [Java, C] LinkedList after offer(): [Java, C, Swift]
예제: LinkedList를 Deque로 사용
import java.util.LinkedList;
import java.util.Deque;
class Main {
public static void main(String[] args){
Deque<String> animals = new LinkedList<>();
animals.add("Cow");
System.out.println("LinkedList: " + animals);
animals.addFirst("Dog");
System.out.println("LinkedList after addFirst(): " + animals);
animals.addLast("Zebra");
System.out.println("LinkedList after addLast(): " + animals);
animals.removeFirst();
System.out.println("LinkedList after removeFirst(): " + animals);
animals.removeLast();
System.out.println("LinkedList after removeLast(): " + animals);
}
}
출력
LinkedList: [Cow] LinkedList after addFirst(): [Dog, Cow] LinkedList after addLast(): [Dog, Cow, Zebra] LinkedList after removeFirst(): [Cow, Zebra] LinkedList after removeLast(): [Cow]
LinkedList 순회하기
향상된 for-루프로 간결하게 순회:
import java.util.LinkedList;
class Main {
public static void main(String[] args){
LinkedList<String> animals = new LinkedList<>();
animals.add("Cow");
animals.add("Cat");
animals.add("Dog");
System.out.println("LinkedList: " + animals);
System.out.println("Accessing linked list elements:");
for(String animal: animals){
System.out.print(animal + ", ");
}
}
}
출력
LinkedList: [Cow, Cat, Dog] Accessing linked list elements: Cow, Cat, Dog,
LinkedList vs ArrayList
둘 다 List를 구현하지만 성능 특성이 다릅니다:
| LinkedList | ArrayList |
List, Queue, Deque 구현 | List 구현 |
| 노드가 prev, data, next 저장 | 배열 슬롯당 단일 요소 |
| 이중 연결 구조 | 크기 조절 가능 배열 |
| 위치 알면 삽입/삭제 O(1) | 인덱스 뒤 삽입 시 O(n) 시프트 필요 |
| 임의 접근 시 순회 필요 O(n) | 직접 인덱스 접근 O(1) |
참고: LinkedList는 인터페이스 중 하나로 인스턴스화 가능:
// List 인터페이스로
List<String> animals1 = new LinkedList<>();
// Queue 인터페이스로
Queue<String> animals2 = new LinkedList<>();
// Deque 인터페이스로
Deque<String> animals3 = new LinkedList<>();
인터페이스 참조 사용 시 해당 인터페이스에 정의된 메서드만 사용 가능합니다.