티스토리 뷰
728x90
반응형
forEach와 stream() 메서드는 둘 다 컬렉션의 요소를 반복(iterate)하는 기능을 제공하지만, 동작 방식과 목적이 다릅니다.
✅ forEach vs. stream() 차이점 요약
구분 forEach stream()
목적 | 단순 반복(iteration) 수행 | 데이터 변환 및 가공 |
반환값 | 없음 (void) | 변환된 스트림을 반환 |
병렬 처리 | parallelStream().forEach() 사용 가능하지만, 비순차적 실행 가능성 있음 | parallelStream()을 활용하면 병렬 처리가 안정적으로 가능 |
사용 예 | 로그 출력, 데이터 출력 등 | 필터링, 변환, 수집 등 데이터 가공 |
원본 컬렉션 변경 여부 | 원본 컬렉션 수정 가능 | 원본 컬렉션을 변경하지 않음 (불변성 유지) |
1️⃣ forEach : 단순 반복(iteration)
- forEach는 스트림이 아닌 컬렉션(List, Set, Map 등)에 직접 사용 가능합니다.
- 주로 컬렉션의 요소를 하나씩 순회하면서 출력하거나 상태를 변경할 때 사용합니다.
✅ forEach 예제 (출력용)
List<String> names = List.of("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));
출력
Alice
Bob
Charlie
- 단순한 반복(iteration) 기능만 수행합니다.
- 반환값이 없고(void), 연산 결과를 저장할 수도 없습니다.
2️⃣ stream()
- 함수형 프로그래밍 스타일을 제공하며, 데이터 변환과 가공이 가능하도록 설계되었습니다.
- 원본 컬렉션을 변경하지 않으며, map(), filter(), collect() 같은 연산을 통해 변형된 데이터를 만들 수 있습니다.
✅ stream() 예제 (대문자로 변환 후 리스트 수집)
List<String> names = List.of("Alice", "Bob", "Charlie");
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase) // 모든 이름을 대문자로 변환
.collect(Collectors.toList()); // 리스트로 수집
System.out.println(upperCaseNames);
출력
[ALICE, BOB, CHARLIE]
- 원본 리스트는 변경되지 않으며, 새로운 리스트를 생성합니다.
- map(String::toUpperCase)를 사용해 데이터 변환이 가능합니다.
3️⃣ forEach vs. stream() 코드 비교
🚀 forEach (데이터를 변환하려고 할 때 문제 발생)
List<String> names = List.of("Alice", "Bob", "Charlie");
List<String> upperCaseNames = new ArrayList<>();
names.forEach(name -> upperCaseNames.add(name.toUpperCase()));
System.out.println(upperCaseNames);
- upperCaseNames라는 새로운 리스트를 만들고, forEach 안에서 값을 추가해야 합니다.
- 코드가 명확하지 않고, 병렬 처리를 지원하지 않습니다.
✅ stream() (데이터 변환을 더 간결하게)
List<String> upperCaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
System.out.println(upperCaseNames);
- 코드가 더 간결하고 효율적입니다.
- 병렬 처리를 원하면 .parallelStream()을 사용할 수 있습니다.
4️⃣ 병렬 처리 (Parallel Processing) 차이점
🚨 forEach 병렬 처리 문제점
List<Integer> numbers = IntStream.rangeClosed(1, 10)
.boxed()
.collect(Collectors.toList());
numbers.parallelStream().forEach(n -> System.out.print(n + " "));
출력 (실행할 때마다 순서가 달라짐)
3 1 4 2 5 6 7 9 8 10
- parallelStream().forEach()를 사용하면 순서 보장이 어렵습니다.
✅ stream()을 사용한 병렬 처리 (순서 보장)
numbers.parallelStream()
.forEachOrdered(n -> System.out.print(n + " "));
출력 (순서 보장)
1 2 3 4 5 6 7 8 9 10
- forEachOrdered()를 사용하면 병렬 처리 시에도 순서를 유지할 수 있습니다.
✅ 결론 (언제 forEach vs. stream()을 사용할까?)
상황 forEach 사용 stream() 사용
단순 반복 | ✅ | ❌ |
데이터 변환 | ❌ | ✅ |
요소 필터링 | ❌ | ✅ |
결과를 새로운 리스트/셋으로 만들 때 | ❌ | ✅ |
병렬 처리 | ❌ (parallelStream().forEach()는 순서 문제 발생 가능) | ✅ (forEachOrdered() 사용 가능) |
✨ 정리하면
- 단순 반복(iteration)만 필요하면 forEach
- 데이터 변환 및 가공이 필요하면 stream()
- 병렬 처리가 필요하면 stream().parallelStream()
- 원본 컬렉션을 변경하려면 forEach, 불변성을 유지하려면 stream()
🚀 마무리
- forEach는 단순한 반복(iteration) 용도로 사용됩니다.
- stream()은 변환(map), 필터링(filter), 수집(collect) 등 다양한 데이터 가공 기능을 제공합니다.
- 데이터를 변환해야 한다면 stream()이 더 적절합니다.
- 병렬 처리가 필요할 경우 parallelStream()을 사용할 수 있지만, 순서가 중요하면 forEachOrdered()를 활용해야 합니다.
728x90
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- .submit()
- 표현 언어(expression language)
- 스프링 프레임워크(spring framewordk)
- java web-mvc
- 스프링 시큐리티(spring security)
- system.io
- 람다식(lambda expression)
- docker
- 스프링 시큐리티(spring security)-http basic 인증
- REST API
- React
- await
- In App Purchase
- 진수 변환
- jstl(java standard tag library)
- 문자 자르기
- 제품 등록
- MainActor
- nl2br
- java-개발 환경 설정하기
- 스프링 프레임워크(spring framework)
- error-java
- 메이븐(maven)
- jstl(java standard tag library)-core
- java 키워드 정리
- 인텔리제이(intellij)
- 특정 문자를 기준으로 자르기
- System.Diagnostics
- java.sql
- jsp 오픈 소스
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
글 보관함