Java Stream API

break 없는 while loop·2025년 4월 13일
post-thumbnail

1. Stream이란?

  • 데이터를 일종의 데이터 흐름(stream)으로 보고 처리
  • 원본 컬렉션은 변경되지 않음(immutable)
  • 연산을 연결(chaining)할 수 있음
  • 중간 연산(변환)최종 연산(결과)으로 나뉘어 있음

2. 기본 구조

List<String> names = List.of("kim", "lee", "park");

names.strea() // stream 생성
	.filter(name -> name.startsWith("k")) 	// 중간 연산
    .map(String::toUpperCase) 				// 중간 연산
    .forEach(System.out::println); 			// 최종 연산

3. 주요 연산 정리

분류메서드설명
📌 생성stream(), Stream.of(...)컬렉션 또는 배열로부터 스트림 생성
📌 필터링filter()조건을 만족하는 요소만 통과
📌 변환map()요소를 다른 값으로 변환
📌 정렬sorted()기본 정렬 / 커스텀 정렬
📌 제한limit(n), skip(n)앞에서 n개 제한 / n개 건너뛰기
📌 수집collect()결과를 리스트, 맵 등으로 수집
📌 반복forEach()각각의 요소에 작업 수행
📌 검사anyMatch(), allMatch(), noneMatch()조건 검사
📌 검색findFirst(), findAny()요소 하나 찾기 (Optional 반환)
📌 통계count(), max(), min(), sum()숫자형 요소의 통계 계산

4. 예제들

🔹 필터 + 변환 + 출력

List<String> list = List.of("apple", "banana", "avocado");

list.sream()
	.filter(s -> s.startsWith("a"))
    .map(String::toUppercase)
    .forEach(System.out::println);

출력:
APPLE
AVOCADO

🔹 정렬

list.stream()
	.sorted() // 오름차순
    .forEach(System.out::println);
list.stream()
	.sorted(Comparator.reverseOrder()) // 내림차순
    .forEach(System.out::println);

🔹 수집 (List로 다시 받기)

List<String> upperList = list.stream()
	.map(String::toUpperCase)
    .collect(Collectors.toList());

🔹 숫자형 리스트 예: 최대값

List<Integer> nums = List.of(5, 2, 8, 3);
int max = nums.stream().max(Integer::compare).orElse(-1);

5. 병렬 스트림 (병렬 처리)

list.parallelStream()
	.map(...)
    .collect(...);
  • CPU 코어를 병렬로 사용 (속도 개선 가능)
  • 순서 보장 안 됨 → 주의!
  • 병렬 처리에서 순서 보장하려면 forEachOrdered() 사용 (단, 성능 손해 있음)
    • 하지만 병렬로 정렬 후 순차로 바꾸면 병렬 처리한 이점이 사라짐
    • 정렬이 핵심이면 애초에 순차 스트림 쓰는 게 더 효율적일 수 있음
list.parallelStream()
	.sorted()
    .forEachOrdered(System.out::println);

6. 스트림 vs 일반 반복문

항목스트림일반 반복문
코드 가독성좋음 (간결)길고 명령형
성능거의 동일 / 병렬처리 가능순차처리
유연성연산 조합 쉬움복잡함
디버깅어려움 (peek 사용 가능)쉬움

7. 참고 팁

  • .peek(System.out::println) 으로 중간 디버깅 가능
  • Optional로 리턴되는 findFirst(), max() 등은 .orElse() 같이 쓰기
  • Collectors.toMap() 같은 고급 수집기도 있음
List<Customer> customers = List.of(
	new Customer(1, "Kim"),
    new Customer(2, "Lee"),
    new Customer(3, "Park")
);

// ID를 key로, 이름을 value로 Map 만들기
Map<Integer, String> map = customers.stream()
	.collect(Collectors.toMap(
    	Customer::getId, 		// keyMapper
        Customer::getName		// valueMapper
));

// 전체 객체를 Map에 저장 (id 기준)
Map<Integer, Customer> map = customers.stream()
	.collect(Collectors.toMap(
    	Customer::getId,
        Function.identity()
));

// 중복 키가 있을 경우? → mergeFunction 필요
Map<Integer, Customer> map = customers.stream()
	.collect(Collectors.toMap(
    	Customer::getid,
        Customer::getName,
        (name1, name2) -> name1 + "/" + name2 // 충돌 해결
));
```![](https://velog.velcdn.com/images/kys6453/post/4b0006b8-af95-460f-a6a5-ad642eaf3cce/image.png)
profile
프로그래밍 지식 아카이브용

0개의 댓글