Contents
공부용 코드공부용 코드
코드 결과

map


filter


count, sort, distinct



mapToInt, sum, min, max, average


groupyby


코드
package ex02;
import lombok.Data;
import java.util.Arrays;
import java.util.Comparator;
import java.util.stream.Collectors;
public class StEx01 {
public static void main(String[] args) {
var list = Arrays.asList(1, 2, 3, 4, 5);
Cart c1 = new Cart(1, "바나나", 1000);
Cart c2 = new Cart(2, "바나나", 1000);
Cart c3 = new Cart(3, "딸기", 2000);
Cart c4 = new Cart(4, "사과", 3000);
var cartList = Arrays.asList(c1, c2, c3, c4);
// 1. map (가공)
var new11 = list.stream().map(i -> i * 2).toList();
System.out.println(new11);
var new12 = list.stream()
.map(i -> i * 2)
.filter(i -> i != 10)
.toList();
System.out.println(new12);
// 2. filter (검색, 삭제)
var new21 = list.stream()
.filter(i -> i < 3)
.toList();
System.out.println(new21);
// 3. count(개수), sort(정렬), distinct(중복제거)
var new31 = list.stream()
.sorted(Comparator.reverseOrder())
.map(i -> i / 3)
.distinct()
.count();
System.out.println(new31);
// 4. mapToInt, sum, min, max, average
var new41 = cartList.stream() // 1. 물가에 던져진 cart 4개
.mapToInt(cart -> cart.getPrice()) // 2. 물가에 던져진 Integer 4개
.min();
System.out.println(new41);
// 5. groupby [key=[c1, c2], key=[c3], key=[c4]]
var new51 = cartList.stream()
.collect(Collectors.groupingBy(cart -> cart.getName()))
.entrySet()
.stream()
.map(en -> en.getValue())
.toList();
System.out.println(new51);
}
@Data
static class Cart {
private int id;
private String name;
private int price;
public Cart(int id, String name, int price) {
this.id = id;
this.name = name;
this.price = price;
}
}
}
Java의 Stream API는 Java 8에서 도입된 기능으로, 컬렉션 데이터를 다루는 데 있어 더 효율적이고 선언적인 방법을 제공합니다. Stream API는 컬렉션에 저장된 데이터를 처리(필터링, 정렬, 변환 등)하는데 유용하며, 함수형 프로그래밍 스타일을 지원합니다.
기존의 입출력 스트림과는 전혀 다른 개념이니 혼동하지 않도록 합니다.
주요 개념
- Stream:
- 데이터의 순차적인 흐름을 나타냅니다. 컬렉션에서 데이터를 추출하여 스트림을 생성할 수 있습니다.
- 중간 연산 (Intermediate Operations):
- 스트림을 변환하지만, 결과를 최종적으로 반환하지 않는 연산입니다. 중간 연산은 항상 또 다른 스트림을 반환하며, 이는 체이닝(chaining)될 수 있습니다. 예:
filter
,map
,sorted
.
- 최종 연산 (Terminal Operations):
- 스트림을 처리하고 결과를 반환합니다. 최종 연산이 호출되면 스트림의 데이터가 소비되며, 이후에 스트림을 다시 사용할 수 없습니다. 예:
forEach
,collect
,reduce
.
예제 1: Count
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> r1 = names.stream().filter(name -> name.length() > 3).toList();
r1.forEach(s -> System.out.println(s));
Long r2 = names.stream().filter(name -> name.length() > 3).count();
System.out.println(r2);
- 설명:
filter
: 이름의 길이가 3보다 큰 요소만 필터링합니다.toList
: 필터링된 결과를 리스트로 반환합니다.forEach
: 결과를 하나씩 출력합니다.count
: 필터링된 요소의 개수를 세고 출력합니다.
- 결과:
- 필터링된 리스트 출력: "Alice", "Charlie", "David"
- 필터링된 요소의 개수 출력:
3
예제 2: Sort
List<Integer> nums = Arrays.asList(5, 3, 1, 4, 2, 5);
// 정렬을 한 뒤, 중복을 제거하고, 반복문으로 출력한다.
nums.stream().sorted().distinct().forEach(integer -> System.out.println(integer));
- 설명:
sorted
: 리스트의 요소를 오름차순으로 정렬합니다.distinct
: 중복된 요소를 제거합니다.forEach
: 정렬되고 중복이 제거된 요소를 하나씩 출력합니다.
- 결과:
- 출력: 1, 2, 3, 4, 5
예제 3: Map
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> newNames = names.stream().map(name -> name.toLowerCase())
.filter(name -> name.length() > 3)
.toList();
newNames.forEach(name -> System.out.println(name));
- 설명:
map
: 각 이름을 소문자로 변환합니다.filter
: 이름의 길이가 3보다 큰 요소만 필터링합니다.toList
: 필터링된 결과를 리스트로 반환합니다.forEach
: 결과를 하나씩 출력합니다.
- 결과:
- 출력: "alice", "charlie", "david"
예제 4: Group
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David", "anna");
// 리턴 타입 : Map<Character, List<String>>
// 최근 버전은 var로 모든 형을 대체해서 쓸 수 있게 패치되었다.
var groupData = names.stream()
.map(name -> name.toUpperCase())
.collect(Collectors.groupingBy(name -> name.charAt(0)));
System.out.println(groupData);
- 설명:
map
: 각 이름을 대문자로 변환합니다.collect
: 이름의 첫 글자를 기준으로 그룹화하여Map
으로 반환합니다.Collectors.groupingBy
: 그룹화를 수행하는 수집기(collector)를 사용합니다.
- 결과:
- 출력: {A=[ALICE, ANNA], B=[BOB], C=[CHARLIE], D=[DAVID]}
예제 5: Reduce (조인)
List<Integer> nums = Arrays.asList(1, 2, 3, 4);
int sum1 = nums.stream().mapToInt(x -> x).sum();
System.out.println(sum1);
int sum2 = nums.stream().reduce(5, (prev, next) -> {
System.out.println("prev : " + prev);
System.out.println("next : " + next);
System.out.println("----------");
return prev + next;
});
System.out.println(sum2);
- 설명:
mapToInt
및sum
: 스트림의 모든 요소를 정수형으로 변환하고 합계를 계산합니다.reduce
: 초기값5
를 가지고, 스트림의 모든 요소를 더하여 최종 합계를 계산합니다. 중간 값(prev
와next
)을 출력합니다.
- 결과:
sum1
: 10 (1 + 2 + 3 + 4)sum2
: 15 (5 + 1 + 2 + 3 + 4)
추가 주요 개념과 기능
기능 | 설명 | 예제 |
entrySet | Map 객체를 순회할 때 사용. key, value 모두 접근할 때 필요 | map.entrySet().forEach(e -> System.out.println(e.getKey() + " : " + e.getValue())); |
groupingBy | 특정 조건으로 그룹핑할 때 사용 ( Collectors.groupingBy ) | collect(Collectors.groupingBy(x -> x.charAt(0))) |
distinct | 스트림에서 중복을 제거 | stream().distinct() |
limit | 스트림의 일부만 추출 | stream().limit(5) → 앞 5개만 가져오기 |
skip | 앞의 일부 요소를 건너뛰기 | stream().skip(3) → 앞 3개 건너뛰기 |
peek | 중간에 디버깅용으로 값 찍을 때 사용 (forEach 아님) | stream().peek(x -> System.out.println(x)) |
flatMap | 스트림 안에 스트림이 있을 때 평탄화 (2차원 → 1차원) | stream().flatMap(List::stream) |
anyMatch | 하나라도 조건에 맞으면 true | stream().anyMatch(x -> x > 5) |
allMatch | 모두 조건에 맞아야 true | stream().allMatch(x -> x > 5) |
noneMatch | 모두 조건에 안 맞아야 true | stream().noneMatch(x -> x > 5) |
findFirst | 첫 번째 요소 가져오기 (Optional) | stream().findFirst() |
findAny | 병렬 스트림 등에서 아무 요소나 빠르게 가져오기 | parallelStream().findAny() |
min/max | 최소값, 최대값 찾기 | stream().min(Comparator.naturalOrder()) |
간단 예시 추가
1. limit / skip
java
복사
List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
nums.stream().skip(3).limit(5).forEach(System.out::println);
// 출력: 4 5 6 7 8
2. peek (디버깅용)
java
복사
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.peek(name -> System.out.println("Before filter: " + name))
.filter(name -> name.length() > 3)
.peek(name -> System.out.println("After filter: " + name))
.forEach(System.out::println);
3. flatMap
java
복사
List<List<Integer>> listOfLists = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4),
Arrays.asList(5, 6)
);
listOfLists.stream()
.flatMap(List::stream)
.forEach(System.out::println);
// 출력: 1 2 3 4 5 6
4. anyMatch / allMatch / noneMatch
java
복사
List<Integer> nums = Arrays.asList(1, 2, 3, 4, 5);
boolean anyAbove3 = nums.stream().anyMatch(n -> n > 3); // true
boolean allAbove0 = nums.stream().allMatch(n -> n > 0); // true
boolean noneAbove10 = nums.stream().noneMatch(n -> n > 10); // true
System.out.println(anyAbove3);
System.out.println(allAbove0);
System.out.println(noneAbove10);
요약
- 데이터 조작:
filter
,map
,flatMap
- 데이터 흐름 제어:
limit
,skip
,peek
- 결과 수집:
collect
,groupingBy
- 검사:
anyMatch
,allMatch
,noneMatch
- 요소 찾기:
findFirst
,findAny
- 최댓값, 최솟값:
max
,min
- 디버깅용:
peek
- 중복 제거:
distinct
- Map 처리:
entrySet
Share article