컬렉션 프레임워크는 데이터를 저장하고 처리하기 위한 자료구조 클래스들의 집합
왜 사용할까?
1. 프로그래밍 효율성
- 이미 구현된 자료구조를 사용하여 개발 시간을 단축할 수 있음
- 최적화된 알고리즘을 통해 성능을 보장받을 수 있음
2. 재사용성
- 표준화된 방식으로 데이터를 관리할 수 있음
- 여러 프로젝트에서 일관된 방식으로 사용할 수 있음
List 계열: 데이터를 순차적으로 저장
Set 계열: 중복을 허용하지 않는 데이터 집합
Map 계열: 키와 값을 쌍으로 저장하며, 키는 중복을 허용하지 않음
List 컬렉션은 순서를 유지하며 중복을 허용하는 요소들의 집합을 나타내는 인터페이스로, 구현체에 따라 ArrayList, LinkedList 등으로 동작 방식이 달라짐

ArrayList를 사용하면 좋은 경우
- 데이터 검색/조회가 빈번한 경우
- 데이터의 삽입/삭제가 주로 마지막 위치에서 일어나는 경우
- 데이터가 자주 변경되지 않고 주로 읽기 작업이 많은 경우
LinkedList를 사용하면 좋은 경우
- 데이터의 삽입/삭제가 리스트의 시작이나 끝에서 빈번히 발생하는 경우
- 데이터의 크기가 예측이 어렵고 변동이 심한 경우
ArrayList 선언 및 사용 예시
import java.util.ArrayList;
import java.util.List;
public class Solution {
public static void main(String[] args) {
// ArrayList 선언
ArrayList<String> fruits = new ArrayList<>();
// 초기값 추가
fruits.add("Apple"); // "Apple" 추가
fruits.add("Banana"); // "Banana" 추가
fruits.add("Cherry"); // "Cherry" 추가
// ArrayList 초기값과 함께 생성
ArrayList<String> colors = new ArrayList<>(List.of("Red", "Green", "Blue"));
System.out.println("\nColors ArrayList: " + colors);
// ArrayList 요소 접근
System.out.println("First Fruit: " + fruits.get(0)); // 첫 번째 요소 가져오기
// 특정 인덱스에 요소 삽입
fruits.add(1, "Orange"); // 인덱스 1에 "Orange" 삽입
System.out.println("After inserting 'Orange': " + fruits);
// 요소 변경
fruits.set(2, "Blueberry"); // 인덱스 2의 요소를 "Blueberry"로 변경
System.out.println("After updating index 2: " + fruits);
// 요소 제거
fruits.remove(3); // 인덱스 3의 요소 제거
System.out.println("After removing index 3: " + fruits);
fruits.remove("Orange"); // "Orange" 제거
System.out.println("After removing 'Orange': " + fruits);
// ArrayList 크기 확인
System.out.println("ArrayList Size: " + fruits.size());
// ArrayList가 비어 있는지 확인
System.out.println("Is ArrayList Empty? " + fruits.isEmpty());
// for문을 이용한 ArrayList 순회 (인덱스로 값 참조)
System.out.println("\nUsing for loop:");
for (int i = 0; i < fruits.size(); i++) {
System.out.println("Element at index " + i + ": " + fruits.get(i));
}
// for-each문을 이용한 ArrayList 순회 (직접 값 참조)
System.out.println("\nUsing for-each loop:");
for (String fruit : fruits) {
System.out.println("Fruit: " + fruit);
}
}
}

배열
ArrayList
Collections의 주요 기능
1. 정렬(Sorting)
컬렉션의 요소를 자연 정렬 순서 또는 사용자 정의 기준으로 정렬할 수 있음
Collections.sort(List<T>): 자연정렬Collections.sort(List<T>, Comparator<T>): 사용자 정의 정렬Collections.min(Collection<T>)Collections.max(Collection<T>)Collections.frequency(Collection<T>, T)Collections.binarySearch(List<T>, T key)Collections.replaceAll(List<T>, T oldVal, T newVal)Collections.reverse(List<T>)Collections.rotate(List<T>, int distance)Map은 키(Key)와 값(Value)을 하나의 쌍으로 묶어서 저장하는 자료구조

사용하는 이유
주요 활용 상황
HashMap은 Map 인터페이스를 구현한 대표적인 클래스, 가장 자주 사용됨
// 1. 선언
HashMap<String, Integer> map = new HashMap<>();
// 2. 데이터 추가 및 수정
map.put("A", 1); // 키가 "A"인 값에 1 저장
map.putIfAbsent("A", 10); // "A"키가 없을 때만 10 저장
int value = map.getOrDefault("B", 0);// "B"키 조회, 없으면 기본값 0
// 3. 존재 여부 확인
if (map.containsKey("A")) { ... } // "A"키 존재 여부 확인
if (map.containsValue(1)) { ... } // 값 1 존재 여부 확인
// 4. 삭제
map.remove("A"); // "A"키 삭제
map.clear(); // 전체 삭제
// 5. 값 변경하기 (다양한 방법)
HashMap<String, Integer> scores = new HashMap<>();
scores.put("Kim", 80);
// 5-1. 일반적 방식
if (scores.containsKey("Kim")) {
scores.put("Kim", scores.get("Kim") + 10);
}
// 5-2. compute 활용 (람다 사용)
scores.compute("Kim", (key, oldVal) -> oldVal + 10);
// 5-3. 키가 있을 때만 변경 (computeIfPresent)
scores.computeIfPresent("Kim", (key, oldVal) -> oldVal + 10);
// 6. 크기 확인
int size = map.size();
boolean isEmpty = map.isEmpty();
Set은 중복되지 않는 요소들을 저장하는 자료구조
값이 2번 이상 등장하는 것을 허용하지 않으며 각 요소는 유일
순서는 보장하지 않지만 LinkedHaseSet을 사용하면 삽입 순서를 유지할 수 있음

HashSet은 가장 널리 사용되는 Set 구현체 중 하나로 해시 기반으로 요소를 관리
일반적으로 순서를 보장하지 않으며 빠른 검색과 삽입 성능을 자랑함
// 1. 선언
HashSet<String> set = new HashSet<>();
// 2. 데이터 추가 및 삭제
set.add("A"); // 요소 "A" 추가 (중복 요소는 추가되지 않음)
set.remove("A"); // "A" 삭제
set.clear(); // 모든 요소 삭제
// 3. 데이터 확인
boolean exists = set.contains("A"); // "A"가 존재하는지 확인
int size = set.size(); // Set의 크기 확인
boolean empty = set.isEmpty(); // 비었는지 확인
// 4. 집합 연산
Set<String> set1 = new HashSet<>();
Set<String> set2 = new HashSet<>();
// 합집합: set1에 set2의 요소 모두 추가
set1.addAll(set2);
// 교집합: set1과 set2에 모두 있는 요소만 남김
set1.retainAll(set2);
// 차집합: set1에서 set2의 요소 제거 (set1 - set2)
set1.removeAll(set2);