# **코틀린 컬렉션과 스트림 API vs 자바 스트림 API**  

코틀린은 자바와 마찬가지로 **리스트(List), 세트(Set), 맵(Map)** 등의 컬렉션을 제공한다. 하지만 자바와는 다르게, **컬렉션을 더욱 간결하게 다룰 수 있는 함수형 API**를 기본 제공하며, 대부분의 연산을 **람다식과 메서드 체이닝**을 통해 쉽게 수행할 수 있다.  

이번 글에서는 **코틀린의 컬렉션 사용법과 자바 스트림 API와의 차이점**을 비교해보겠다.  

---

## **1. 코틀린 컬렉션 기본 개념**  

### **1.1. 불변(Immutable) vs 가변(Mutable) 컬렉션**  

코틀린의 컬렉션은 **불변형(`listOf`, `setOf`, `mapOf`)**과 **가변형(`mutableListOf`, `mutableSetOf`, `mutableMapOf`)**으로 나뉜다.  
자바에서는 `Collections.unmodifiableList()` 등을 사용해야 하지만, 코틀린에서는 기본적으로 **불변 컬렉션을 사용하도록 유도**한다.  

#### **자바의 리스트 선언**
```java
List<String> immutableList = List.of("A", "B", "C");  // Java 9+
List<String> mutableList = new ArrayList<>();
mutableList.add("A");
mutableList.add("B");
```

#### **코틀린의 리스트 선언**
```kotlin
val immutableList = listOf("A", "B", "C")  // 불변 리스트
val mutableList = mutableListOf("A", "B")  // 가변 리스트
mutableList.add("C")
```
> **차이점 요약:**  
> - **자바**: `List.of()`(불변) vs `ArrayList<>()`(가변)  
> - **코틀린**: `listOf()`(불변) vs `mutableListOf()`(가변)  

---

## **2. 코틀린 컬렉션 사용 예제**  

### **2.1. 리스트(List)**
```kotlin
val numbers = listOf(1, 2, 3, 4, 5)
println(numbers[0])  // 1
println(numbers.size)  // 5
```
가변 리스트:
```kotlin
val mutableNumbers = mutableListOf(1, 2, 3)
mutableNumbers.add(4)
println(mutableNumbers)  // [1, 2, 3, 4]
```

---

### **2.2. 집합(Set)**
```kotlin
val names = setOf("Alice", "Bob", "Charlie")
println(names.contains("Alice"))  // true
```
가변 집합:
```kotlin
val mutableNames = mutableSetOf("Alice", "Bob")
mutableNames.add("Charlie")
```

---

### **2.3. 맵(Map)**
```kotlin
val userMap = mapOf("Alice" to 25, "Bob" to 30)
println(userMap["Alice"])  // 25
```
가변 맵:
```kotlin
val mutableUserMap = mutableMapOf("Alice" to 25)
mutableUserMap["Bob"] = 30
```

---

## **3. 코틀린의 스트림 API vs 자바의 스트림 API**  

자바에서는 컬렉션을 처리할 때 **스트림 API(`Stream`)**를 사용해야 하지만,  
코틀린은 **컬렉션 자체가 스트림 API처럼 동작**한다.  

### **3.1. 자바 스트림 예제**
```java
List<String> names = List.of("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

System.out.println(filteredNames);  // [ALICE]
```
> **자바의 특징:**  
> - `.stream()`을 호출해야 함  
> - `.collect(Collectors.toList())`를 사용해야 리스트 반환  

---

### **3.2. 코틀린 컬렉션 API 예제**
```kotlin
val names = listOf("Alice", "Bob", "Charlie")
val filteredNames = names
    .filter { it.startsWith("A") }
    .map { it.uppercase() }

println(filteredNames)  // [ALICE]
```
> **코틀린의 특징:**  
> - `stream()` 없이 컬렉션 자체에서 메서드 체이닝 가능  
> - `collect()` 없이 리스트 반환  

---

### **3.3. 숫자 리스트 필터링 & 변환**
#### **자바 (Stream API 사용)**
```java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
List<Integer> evenSquares = numbers.stream()
    .filter(n -> n % 2 == 0)
    .map(n -> n * n)
    .collect(Collectors.toList());

System.out.println(evenSquares);  // [4, 16, 36]
```
#### **코틀린 (컬렉션 API 사용)**
```kotlin
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenSquares = numbers
    .filter { it % 2 == 0 }
    .map { it * it }

println(evenSquares)  // [4, 16, 36]
```

> **차이점 요약:**  
> - **자바**: `.stream()` 호출 → `filter()`, `map()` → `.collect(Collectors.toList())` 필요  
> - **코틀린**: 바로 `filter()`, `map()` 사용 가능  

---

## **4. 추가적인 컬렉션 함수들**

### **4.1. `forEach`**
```kotlin
val numbers = listOf(1, 2, 3)
numbers.forEach { println(it) }  
```

### **4.2. `groupBy`**
```kotlin
val words = listOf("apple", "banana", "avocado", "blueberry")
val grouped = words.groupBy { it.first() }
println(grouped)
// {a=[apple, avocado], b=[banana, blueberry]}
```

### **4.3. `associateBy` (키 매핑)**
```kotlin
data class Person(val name: String, val age: Int)

val people = listOf(Person("Alice", 25), Person("Bob", 30))
val personMap = people.associateBy { it.name }
println(personMap["Alice"])  // Person(name=Alice, age=25)
```

---

## **5. 정리: 코틀린 vs 자바 스트림 API 차이점**  

| 기능 | 자바 (Stream API) | 코틀린 (컬렉션 API) |
|------|----------------|----------------|
| 스트림 사용 | `.stream()` 필요 | 컬렉션 자체에서 사용 가능 |
| 리스트 반환 | `.collect(Collectors.toList())` 필요 | 자동 반환 |
| `filter()` 사용 | `filter(n -> 조건)` | `filter { it 조건 }` |
| `map()` 사용 | `map(n -> 변환)` | `map { it 변환 }` |
| 그룹핑 | `.collect(Collectors.groupingBy())` | `groupBy { it 기준 }` |
| 가변 리스트 | `new ArrayList<>()` | `mutableListOf()` |

코틀린은 **컬렉션을 더욱 직관적이고 간결하게 다룰 수 있도록 설계**되었다.  
자바에서 스트림 API를 써야 하는 많은 경우를 **코틀린에서는 기본 컬렉션 함수만으로 해결**할 수 있다.  

> **코틀린으로 스트림 API를 더 쉽게 다룰 수 있다는 점을 기억하자!**