Java Collections Framework - 인터페이스 계층구조와 전체 구조
Java API Reference
/*
Collections Framework:
- 데이터를 저장하고 관리하는 표준화된 방법
- 인터페이스와 구현 클래스로 구성
- java.util 패키지에 포함
*/
public class CollectionsIntro {
public static void main(String[] args) {
System.out.println("=== Collections Framework ===");
System.out.println("목적: 데이터 그룹을 효율적으로 관리");
System.out.println("장점:");
System.out.println(" 1. 표준화된 API");
System.out.println(" 2. 재사용성");
System.out.println(" 3. 성능 최적화");
System.out.println(" 4. 타입 안정성 (제네릭)");
}
}import java.util.*;
public class ArrayVsCollections {
public static void main(String[] args) {
// 배열의 한계
System.out.println("=== 배열 ===");
int[] arr = new int[5]; // 크기 고정!
arr[0] = 10;
arr[1] = 20;
// arr[5] = 30; // ArrayIndexOutOfBoundsException!
System.out.println("크기: " + arr.length); // 5 (고정)
System.out.println("문제점:");
System.out.println(" 1. 크기 고정");
System.out.println(" 2. 삭제 어려움");
System.out.println(" 3. 타입 하나만");
// Collections의 장점
System.out.println("\n=== ArrayList ===");
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
list.add(30); // 자동 확장!
System.out.println("크기: " + list.size()); // 3 (동적)
list.remove(1); // 쉬운 삭제
System.out.println("삭제 후: " + list);
System.out.println("장점:");
System.out.println(" 1. 크기 동적 조절");
System.out.println(" 2. 편리한 메서드");
System.out.println(" 3. 제네릭 타입 안정성");
System.out.println(" 4. 다양한 구현체");
}
}import java.util.*;
public class CollectionInterface {
public static void main(String[] args) {
Collection<String> col = new ArrayList<>();
// 공통 메서드
col.add("Apple"); // 추가
col.remove("Apple"); // 삭제
col.contains("Apple"); // 포함 확인
col.size(); // 크기
col.isEmpty(); // 비어있는지
col.clear(); // 전체 삭제
// 변환
Object[] arr = col.toArray();
String[] strArr = col.toArray(new String[0]);
System.out.println("=== Collection 인터페이스 ===");
System.out.println("하위: List, Set, Queue");
System.out.println("제외: Map (별도 계층)");
}
}import java.util.*;
public class ListInterface {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// List 특화 메서드
list.add(0, "First"); // 인덱스 지정 추가
String item = list.get(0); // 인덱스로 조회
list.set(0, "New"); // 인덱스로 수정
list.remove(0); // 인덱스로 삭제
int index = list.indexOf("Apple");
int lastIndex = list.lastIndexOf("Apple");
List<String> subList = list.subList(0, 2);
System.out.println("=== List 특징 ===");
System.out.println("1. 순서 유지 (인덱스)");
System.out.println("2. 중복 허용");
System.out.println("3. null 허용");
System.out.println("\n구현체: ArrayList, LinkedList");
}
}import java.util.*;
public class SetInterface {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
// Set은 Collection 메서드만 사용
set.add("Apple");
set.add("Apple"); // 중복 무시!
System.out.println(set); // [Apple] (한 번만)
System.out.println("Size: " + set.size()); // 1
System.out.println("=== Set 특징 ===");
System.out.println("1. 중복 불가");
System.out.println("2. 순서 없음 (HashSet)");
System.out.println("3. null 허용 (1개만)");
System.out.println("\n구현체: HashSet, LinkedHashSet, TreeSet");
}
}import java.util.*;
public class QueueInterface {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// Queue 특화 메서드
queue.offer("First"); // 추가
queue.offer("Second");
String head = queue.peek(); // 조회
String removed = queue.poll(); // 조회 + 제거
System.out.println("Head: " + head);
System.out.println("Removed: " + removed);
System.out.println("Queue: " + queue);
System.out.println("\n=== Queue 특징 ===");
System.out.println("1. FIFO 순서");
System.out.println("2. 앞에서 제거, 뒤에서 추가");
System.out.println("\n구현체: LinkedList, PriorityQueue");
}
}import java.util.*;
public class MapInterface {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
// Map 메서드
map.put("Apple", 1000);
int price = map.get("Apple");
map.remove("Apple");
boolean hasKey = map.containsKey("Apple");
boolean hasValue = map.containsValue(1000);
// 순회
for (String key : map.keySet()) {
System.out.println(key + ": " + map.get(key));
}
System.out.println("\n=== Map 특징 ===");
System.out.println("1. Key-Value 쌍");
System.out.println("2. Key는 중복 불가");
System.out.println("3. Value는 중복 가능");
System.out.println("\n구현체: HashMap, LinkedHashMap, TreeMap");
}
}public class Hierarchy {
public static void main(String[] args) {
System.out.println("=== Collection 계층 ===");
System.out.println("Iterable<E>");
System.out.println(" └─ Collection<E>");
System.out.println(" ├─ List<E>");
System.out.println(" │ ├─ ArrayList<E>");
System.out.println(" │ └─ LinkedList<E>");
System.out.println(" ├─ Set<E>");
System.out.println(" │ ├─ HashSet<E>");
System.out.println(" │ ├─ LinkedHashSet<E>");
System.out.println(" │ └─ TreeSet<E>");
System.out.println(" └─ Queue<E>");
System.out.println(" ├─ LinkedList<E>");
System.out.println(" ├─ PriorityQueue<E>");
System.out.println(" └─ ArrayDeque<E>");
System.out.println("\n=== Map 계층 (별도) ===");
System.out.println("Map<K,V>");
System.out.println(" ├─ HashMap<K,V>");
System.out.println(" ├─ LinkedHashMap<K,V>");
System.out.println(" └─ TreeMap<K,V>");
}
}import java.util.*;
public class InterfaceRelation {
public static void main(String[] args) {
// List는 Collection
List<String> list = new ArrayList<>();
Collection<String> col1 = list; // OK
// Set도 Collection
Set<String> set = new HashSet<>();
Collection<String> col2 = set; // OK
// Queue도 Collection
Queue<String> queue = new LinkedList<>();
Collection<String> col3 = queue; // OK
// Map은 Collection 아님!
Map<String, Integer> map = new HashMap<>();
// Collection<String> col4 = map; // 컴파일 에러!
System.out.println("=== 공통점 ===");
System.out.println("List, Set, Queue -> Collection 상속");
System.out.println("공통 메서드: add, remove, size");
System.out.println("\n=== 차이점 ===");
System.out.println("Map -> 별도 계층");
}
}import java.util.*;
public class ListImplementations {
public static void main(String[] args) {
System.out.println("=== List 구현체 ===\n");
// ArrayList
System.out.println("1. ArrayList");
System.out.println(" 내부: 동적 배열");
System.out.println(" 조회: O(1) 빠름");
System.out.println(" 추가/삭제: O(n) 느림");
System.out.println(" 사용: 조회 많을 때");
List<String> arrayList = new ArrayList<>();
arrayList.add("A");
arrayList.add("B");
System.out.println(" 예시: " + arrayList + "\n");
// LinkedList
System.out.println("2. LinkedList");
System.out.println(" 내부: 이중 연결 리스트");
System.out.println(" 조회: O(n) 느림");
System.out.println(" 추가/삭제: O(1) 빠름");
System.out.println(" 사용: 추가/삭제 많을 때");
List<String> linkedList = new LinkedList<>();
linkedList.add("A");
linkedList.add("B");
System.out.println(" 예시: " + linkedList);
}
}import java.util.*;
public class SetImplementations {
public static void main(String[] args) {
System.out.println("=== Set 구현체 ===\n");
// HashSet
System.out.println("1. HashSet");
System.out.println(" 내부: 해시 테이블");
System.out.println(" 순서: 무작위");
System.out.println(" 성능: O(1) 가장 빠름");
Set<String> hashSet = new HashSet<>();
hashSet.add("C");
hashSet.add("A");
hashSet.add("B");
System.out.println(" 예시: " + hashSet + "\n");
// LinkedHashSet
System.out.println("2. LinkedHashSet");
System.out.println(" 순서: 삽입 순서 유지");
System.out.println(" 성능: O(1)");
Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("C");
linkedHashSet.add("A");
linkedHashSet.add("B");
System.out.println(" 예시: " + linkedHashSet + "\n");
// TreeSet
System.out.println("3. TreeSet");
System.out.println(" 내부: 레드-블랙 트리");
System.out.println(" 순서: 자동 정렬");
System.out.println(" 성능: O(log n)");
Set<String> treeSet = new TreeSet<>();
treeSet.add("C");
treeSet.add("A");
treeSet.add("B");
System.out.println(" 예시: " + treeSet);
}
}import java.util.*;
public class MapImplementations {
public static void main(String[] args) {
System.out.println("=== Map 구현체 ===\n");
// HashMap
System.out.println("1. HashMap");
System.out.println(" 내부: 해시 테이블");
System.out.println(" 순서: 무작위");
System.out.println(" 성능: O(1)");
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("C", 3);
hashMap.put("A", 1);
hashMap.put("B", 2);
System.out.println(" 예시: " + hashMap + "\n");
// LinkedHashMap
System.out.println("2. LinkedHashMap");
System.out.println(" 순서: 삽입 순서 유지");
Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("C", 3);
linkedHashMap.put("A", 1);
linkedHashMap.put("B", 2);
System.out.println(" 예시: " + linkedHashMap + "\n");
// TreeMap
System.out.println("3. TreeMap");
System.out.println(" 순서: Key 기준 정렬");
System.out.println(" 성능: O(log n)");
Map<String, Integer> treeMap = new TreeMap<>();
treeMap.put("C", 3);
treeMap.put("A", 1);
treeMap.put("B", 2);
System.out.println(" 예시: " + treeMap);
}
}import java.util.*;
public class QueueImplementations {
public static void main(String[] args) {
System.out.println("=== Queue 구현체 ===\n");
// LinkedList
System.out.println("1. LinkedList (Queue)");
System.out.println(" FIFO 큐");
Queue<String> queue = new LinkedList<>();
queue.offer("A");
queue.offer("B");
System.out.println(" 예시: " + queue + "\n");
// PriorityQueue
System.out.println("2. PriorityQueue");
System.out.println(" 우선순위 큐");
System.out.println(" 자동 정렬");
Queue<Integer> pq = new PriorityQueue<>();
pq.offer(3);
pq.offer(1);
pq.offer(2);
System.out.println(" Poll: " + pq.poll() + "\n");
// ArrayDeque
System.out.println("3. ArrayDeque");
System.out.println(" 양방향 큐");
System.out.println(" Stack보다 빠름");
Deque<String> deque = new ArrayDeque<>();
deque.offerFirst("A");
deque.offerLast("B");
System.out.println(" 예시: " + deque);
}
}public class SelectionGuide {
public static void main(String[] args) {
System.out.println("=== 자료구조 선택 ===\n");
System.out.println("Q1. Key-Value 쌍?");
System.out.println(" YES -> Map");
System.out.println(" 순서 불필요: HashMap");
System.out.println(" 삽입 순서: LinkedHashMap");
System.out.println(" 정렬 필요: TreeMap");
System.out.println("\n NO -> Collection\n");
System.out.println("Q2. 중복 허용?");
System.out.println(" YES -> List");
System.out.println(" 조회 많음: ArrayList");
System.out.println(" 추가/삭제: LinkedList");
System.out.println("\n NO -> Set");
System.out.println(" 순서 불필요: HashSet");
System.out.println(" 삽입 순서: LinkedHashSet");
System.out.println(" 정렬 필요: TreeSet");
System.out.println("\nQ3. 대기열?");
System.out.println(" FIFO: LinkedList");
System.out.println(" 우선순위: PriorityQueue");
System.out.println(" Stack: ArrayDeque");
}
}public class TimeComplexity {
public static void main(String[] args) {
System.out.println("=== 시간 복잡도 ===\n");
System.out.println("ArrayList:");
System.out.println(" get: O(1)");
System.out.println(" add: O(1) 평균");
System.out.println(" add(i,e): O(n)");
System.out.println(" remove: O(n)");
System.out.println(" contains: O(n)\n");
System.out.println("LinkedList:");
System.out.println(" get: O(n)");
System.out.println(" add: O(1)");
System.out.println(" remove: O(1)");
System.out.println(" contains: O(n)\n");
System.out.println("HashSet/HashMap:");
System.out.println(" add/put: O(1)");
System.out.println(" contains/get: O(1)");
System.out.println(" remove: O(1)\n");
System.out.println("TreeSet/TreeMap:");
System.out.println(" add/put: O(log n)");
System.out.println(" contains/get: O(log n)");
System.out.println(" remove: O(log n)");
}
}import java.util.*;
public class RealWorldExamples {
public static void main(String[] args) {
System.out.println("=== 실전 사례 ===\n");
// 1. 학생 목록
List<String> students = new ArrayList<>();
students.add("Alice");
students.add("Bob");
students.add("Alice");
System.out.println("1. 학생 목록: " + students);
System.out.println(" -> ArrayList (순서, 중복)\n");
// 2. 고유 방문자
Set<String> visitors = new HashSet<>();
visitors.add("User1");
visitors.add("User1");
visitors.add("User2");
System.out.println("2. 방문자: " + visitors);
System.out.println(" -> HashSet (중복 제거)\n");
// 3. 사용자 정보
Map<Integer, String> users = new HashMap<>();
users.put(1, "Alice");
users.put(2, "Bob");
System.out.println("3. 사용자: " + users);
System.out.println(" -> HashMap (ID->이름)\n");
// 4. 대기열
Queue<String> waitingList = new LinkedList<>();
waitingList.offer("First");
waitingList.offer("Second");
System.out.println("4. 대기열: " + waitingList);
System.out.println(" -> Queue (FIFO)\n");
// 5. 우선순위
Queue<Integer> tasks = new PriorityQueue<>();
tasks.offer(3);
tasks.offer(1);
tasks.offer(2);
System.out.println("5. 가장 중요: " + tasks.poll());
System.out.println(" -> PriorityQueue (우선순위)");
}
}// 각 상황에 맞는 자료구조 선택
public class Problem1 {
public static void main(String[] args) {
System.out.println("=== 자료구조 선택 문제 ===\n");
System.out.println("1. 학생 성적 (학번->성적)");
System.out.println("2. 로또 번호 (중복 없는 6개)");
System.out.println("3. 브라우저 뒤로가기");
System.out.println("4. 프린터 대기열");
System.out.println("5. 영어 단어장 (정렬)");
}
}정답:
정답 보기
import java.util.*;
public class Problem1 {
public static void main(String[] args) {
// 1. 학생 성적
Map<Integer, Integer> scores = new HashMap<>();
scores.put(20240101, 95);
scores.put(20240102, 88);
System.out.println("1. HashMap - Key-Value\n");
// 2. 로또 번호
Set<Integer> lotto = new HashSet<>();
while (lotto.size() < 6) {
lotto.add((int)(Math.random() * 45) + 1);
}
System.out.println("2. HashSet - 중복 제거");
System.out.println(" " + lotto + "\n");
// 3. 브라우저 뒤로가기
Deque<String> history = new ArrayDeque<>();
history.push("google.com");
history.push("naver.com");
String back = history.pop();
System.out.println("3. ArrayDeque - LIFO\n");
// 4. 프린터 대기열
Queue<String> printQueue = new LinkedList<>();
printQueue.offer("Doc1");
printQueue.offer("Doc2");
String next = printQueue.poll();
System.out.println("4. LinkedList - FIFO\n");
// 5. 영어 단어장
Set<String> dict = new TreeSet<>();
dict.add("zebra");
dict.add("apple");
dict.add("banana");
System.out.println("5. TreeSet - 정렬");
System.out.println(" " + dict);
}
}// ArrayList vs LinkedList 성능
import java.util.*;
public class Problem2 {
public static void main(String[] args) {
int n = 100000;
// ArrayList
List<Integer> arrayList = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
arrayList.add(i);
}
long time1 = System.currentTimeMillis() - start;
// LinkedList
List<Integer> linkedList = new LinkedList<>();
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
linkedList.add(i);
}
long time2 = System.currentTimeMillis() - start;
System.out.println("ArrayList: " + time1 + "ms");
System.out.println("LinkedList: " + time2 + "ms");
}
}정답:
정답 보기
import java.util.*;
public class Problem2 {
public static void main(String[] args) {
System.out.println("=== 끝에 추가 ===");
testAppend(100000);
System.out.println("\n=== 중간 삽입 ===");
testInsert(1000);
System.out.println("\n=== 인덱스 조회 ===");
testGet(100000);
}
static void testAppend(int n) {
List<Integer> al = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) al.add(i);
long time1 = System.currentTimeMillis() - start;
List<Integer> ll = new LinkedList<>();
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) ll.add(i);
long time2 = System.currentTimeMillis() - start;
System.out.println("ArrayList: " + time1 + "ms");
System.out.println("LinkedList: " + time2 + "ms");
System.out.println("-> ArrayList 빠름");
}
static void testInsert(int n) {
List<Integer> al = new ArrayList<>();
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) al.add(0, i);
long time1 = System.currentTimeMillis() - start;
List<Integer> ll = new LinkedList<>();
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) ll.add(0, i);
long time2 = System.currentTimeMillis() - start;
System.out.println("ArrayList: " + time1 + "ms");
System.out.println("LinkedList: " + time2 + "ms");
System.out.println("-> LinkedList 빠름");
}
static void testGet(int n) {
List<Integer> al = new ArrayList<>();
for (int i = 0; i < n; i++) al.add(i);
List<Integer> ll = new LinkedList<>();
for (int i = 0; i < n; i++) ll.add(i);
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) al.get(i);
long time1 = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
for (int i = 0; i < n; i++) ll.get(i);
long time2 = System.currentTimeMillis() - start;
System.out.println("ArrayList: " + time1 + "ms");
System.out.println("LinkedList: " + time2 + "ms");
System.out.println("-> ArrayList 압도적");
}
}// 리스트 중복 제거 후 정렬
import java.util.*;
public class Problem3 {
public static List<Integer> solve(List<Integer> list) {
// 코드 작성
return null;
}
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(5, 2, 8, 2, 9, 1, 5, 8);
List<Integer> result = solve(nums);
System.out.println("Original: " + nums);
System.out.println("Result: " + result);
}
}정답:
정답 보기
import java.util.*;
import java.util.stream.*;
public class Problem3 {
// 방법 1: TreeSet
public static List<Integer> solve1(List<Integer> list) {
Set<Integer> set = new TreeSet<>(list);
return new ArrayList<>(set);
}
// 방법 2: HashSet + sort
public static List<Integer> solve2(List<Integer> list) {
Set<Integer> set = new HashSet<>(list);
List<Integer> result = new ArrayList<>(set);
Collections.sort(result);
return result;
}
// 방법 3: Stream
public static List<Integer> solve3(List<Integer> list) {
return list.stream()
.distinct()
.sorted()
.collect(Collectors.toList());
}
public static void main(String[] args) {
List<Integer> nums = Arrays.asList(5, 2, 8, 2, 9, 1, 5, 8);
System.out.println("Original: " + nums);
System.out.println("Method 1: " + solve1(nums));
System.out.println("Method 2: " + solve2(nums));
System.out.println("Method 3: " + solve3(nums));
}
}Collection<E>
├─ List<E> // 순서O, 중복O
├─ Set<E> // 중복X
└─ Queue<E> // FIFO
Map<K,V> // Key-Value
// List
ArrayList // 조회 빠름
LinkedList // 추가/삭제 빠름
// Set
HashSet // 가장 빠름
LinkedHashSet // 순서 유지
TreeSet // 정렬
// Map
HashMap // 가장 빠름
LinkedHashMap // 순서 유지
TreeMap // 정렬
// Queue
LinkedList // FIFO
PriorityQueue // 우선순위
ArrayDeque // Stack중복 허용? -> List
조회 많음 -> ArrayList
삽입/삭제 -> LinkedList
중복 불가? -> Set
순서X -> HashSet
순서O -> LinkedHashSet
정렬 -> TreeSet
Key-Value? -> Map
일반 -> HashMap
순서 -> LinkedHashMap
정렬 -> TreeMap