forEach() 메소드컬렉션이나 배열의 원소를 다룰 때, 원소의 반복 처리를 프로그램에서 명시적으로 제어하는 방식
원소를 프로그램에서 선언된 변수로 복사한 후 작업 처리
for, 향상된 for, while, do-while, Iterator 등을 이용한 반복 작업 → 외부 반복
forEach() 메소드원소의 반복 처리를 컬렉션 또는 스트림과 같은 데이터 구조 내부에서 반복 처리하는 방식
// 예: 컬렉션의 forEach() 메소드 이용, 매개변수로 람다식을 지정
// forEach() 메소드는 함수형 인터페이스인 Consumer 객체를 인자로 받음
List<String> names = Arrays.asList("Kim", "Lee", "Park");
//내부 반복
names.forEach(item -> System.out.println("내부 반복: " + item));
컬렉션과 배열과 같은 데이터 소스로부터 만들어지는 원소의 시퀀스를 표현하며, 간결하고 효율적 처리 방법을 제공하는 인터페이스
내부 반복과 함수형 프로그래밍 방식 지원
멀티코어 CPU를 활용한 병렬 처리 지원
관련 클래스와 인터페이스는 java.util.stream 패키지에 있음
다양한 집합체 연산을 지원함 (중간처리 연산과 최종처리 연산)
filter(), map(), sorted(), count(), collect(), anyMatch() ...
데이터 원본으로부터 스트림 생성 → 원본 데이터 변경❌
스트림은 일회용
스트림 연산을 파이프라인 형태로 연결할 수 있음
지연 평가를 통해 연산을 최적화

IntStream, LongStream, DoubleStream 인터페이스
기본형
int,long,double형의 원소로 이루어진 데이터를 다루기 위한 스트림
static IntStream range(int, int)
static IntStream rangeClosed(int, int)
static IntStream of(int... values)
sum(), average(), min(), max(), ...
filter(), map(), reduce(), ...
System.out.println(IntStream.rangeClosed(1, 100).sum());
System.out.println(IntStream.rangeClosed(1, 100).average().getAsDouble());
System.out.println(IntStream.rangeClosed(1, 100).min().getAsInt());
System.out.println(IntStream.rangeClosed(1, 100).max().getAsInt());
Arrays.stream()를 사용하여 배열로부터 스트림 생성 가능
Array 클래스에서 제공되는 메소드static DoubleStream stream(double[] array)
static IntStream stream(int[] array)
static <T> Stream<T> stream(T[])
// 원소가 객체인 배열로부터 스트림 생성
// Stream은 제네릭 인터페이스
// 문자열 배열 스트림
String[] strArray = { "홍길동", "이순신", "김유신" };
Stream<String> strStream = Arrays.stream(strArray);
strStream.forEach(item -> System.out.println(item));
// 정수 배열 스트림
int[] intArray = { 1, 2, 3 };
IntStream intStream = Arrays.stream(intArray);
intStream.forEach(item -> System.out.println(item));
File.lines(Path)를 사용하여 텍스트 파일로부터 행 단위 문자열로 구성된 스트림 생성 가능
Path path = Paths.get("c:\\data\\data.txt");
Stream<String> fileStream = Files.lines(path);
fileStream.forEach(line -> System.out.println(line));
fileStream.close();
Collection 유형의 객체인 경우
Collection인터페이스에서stream()과parallelStream()메소드가 디폴트 메소드로 제공
parallelStream()은 병렬처리가 가능한 스트림을 리턴Hashset, ArraySet, LinkedList 객체 등으로부터 스트림을 생성할 때 사용
HashMap 객체의 경우
entrySet()을 사용하여 Set 유형의 객체를 얻음stream또는parallelStream메소드를 사용하여 스트림 생성
컬렉션, 배열, 또는 파일로부터 생성된 스트림에 어떤 처리를 수행하고 새로운 스트림이 만들어지며, 계속해서 이러한 처리 과정을 반복하는 것

filter(), map(), sorted() 등의 연산중간연산을 거친 스트림에 대해 최종적인 결과를 만들거나 동작을 수행하는 부분
스트림 파이프라인에서 마지막에 한 번만 수행됨
forEach(), collect(), count(), anyMatch, reduce() 등
List < String > words = Arrays.asList("apple", "banana", "cherry", "Avocado");
long count = words.stream() // 원본 스트림
.map(String::toUpperCase) // 중간 연산
.filter(word - > word.startsWith("A")) // 중간연산
.count(); // 최종연산
System.out.println(count); // 2가 출력됨
메소드의 연속적 호출

컬렉션 원소들 중에서 중복을 제거하거나 특정 조건을 만족하는 원소만 추출하여 새로운 스트림을 생성하는 작업
Stream<T>, IntStream, LongStream, DoubleStream에서 필터링 메소드는 중간 연산이므로 같은 스트림을 리턴함distinct() 메소드를 사용hashCode()의 리턴값 동일equals()로 비교: true가 반환되면 중복으로 판단filter() 메소드 사용💡
filter()메소드
filter()메소드의 매개 변수는 함수형 인터페이스true또는false를 리턴하는 람다식을 매개변수로 전달
스트림의 원소를 다른 형태로 변환하는 작업
하나의 스트림을 다른 스트림으로 가공하는 과정
| 메서드 | 설명 |
|---|---|
map() | 일반 객체 스트림을 다른 객체 스트림으로 변환 |
mapToInt() | 객체 스트림을 **기본형 IntStream**으로 변환 |
flatMap() / flatMapToInt() | 요소를 스트림으로 변환 후, 여러 스트림을 하나로 합침 (평탄화) |
asDoubleStream() / asLongStream() | IntStream을 다른 기본형 스트림으로 변환 |
boxed() | 기본형 스트림을 객체 스트림 (예: IntStream → Stream<Integer>) 으로 변환 |
map은 1:1 변환,flatMap은 1\:N 변환 후 평탄화에 적합함boxed()는 기본형을 객체로 감싸는 과정 (오토박싱)스트림의 원소들을 오름차순 또는 내림차순으로 정렬하여 새로운 스트림을 생성하는 작업
Stream<T>에서 sorted() 메소드 사용
정렬된 새로운 스트림 리턴
T 유형의 객체(원소)는 Comparable이어야 하며, 크기 비교에 compareTo() 메소드 사용
기본형에 대응되는 포장 클래스는 모두 Comparable임
💡
Comparable<T>
Comparable<T>은 "자연 순서(Natural Ordering)"를 정의하기 위해 사용하는 인터페이스이다.- 예: 문자열의 사전 순, 숫자의 오름차순 등
스트림의 원소들을 하나씩 순회하면서 반복적으로 처리하고 새로운 스트림을 생성하는 작업
peek 메소드각 요소를 순회하며 주어진 동작(람다식)을 수행하는 중간 연산으로, 디버깅이나 로깅에 자주 사용됨
peek()와 anyMatch()를 조합하면 처리되는 원소를, 조건식에서 처음 true가 되는 원소까지로 제한하게 됨💡
forEach() vs anyMatch()
forEach()메소드는 각 요소를 반복하며 주어진 조건(람다식)을 수행하는 종료 연산anyMatch()메소드는 종료 연산으로 주어진 조건(람다식)을 만족하는 요소를 찾으면 검색(순회)를 중단함
중간 처리를 거친 스트림에 대해 집계나 결과 출력 등의 최종 처리를 수행하는 최종연산
집계(합계, 평균, 최대, 최소 등), 매칭, 수집 등의 작업 수행
스트림 파이프라인의 마지막 단계에서 사용되며, 스트림을 다시 사용할 수 없게 함
종료 연산이 수행되기 전까지는 스트림 파이프라인이 실제로 실행되지 않음 lazy evaluation
지연 평가를 통해 스트림 파이프라인을 효율적으로 구성
→ 필요한 결과 얻음
원수들의 개수, 합계, 평균, 최댓값, 최솟값 등을 구하는 최종처리
count()
sum()
average()
max()
min()
IntStream에서 average(), max(), min()는 OptionalInt | OptionalDouble값을 리턴
→ getAsInt() 또는 getAsDouble()로 값을 변환해야 함

스트림의 원소들이 특정 조건을 만족하는지를 확인하는 최종처리
anyMatch(): 하나라도 만족 → trueallMatch(): 모두 만족해야 → truenoneMatch(): 아무도 만족하지 않으면 → trueList<Integer> nums = List.of(1, 2, 3, 4, 5);
nums.stream().anyMatch(n -> n > 4); // true (5가 조건 만족)
nums.stream().allMatch(n -> n < 10); // true (모두 10보다 작음)
nums.stream().noneMatch(n -> n < 0); // true (음수 없음)
스트림의 원소들을 필터링 또는 매핑한 후 최종적으로 새로운 컬렉션(List, Set, Map)을 생성하는 종료 연산
Collectors 클래스는 스트림의 요소들을 수집하는 데 다양한 static 유틸리티 메소드 제공collect()의 인자로 사용됨// 남성 회원만 필터링하여 리스트로 수집
List<Member> male_members = members.stream()
.filter(member -> member.getGender().equals("남"))
.collect(Collectors.toList());
// 남성 회원 출력
male_members.stream()
.forEach(member -> System.out.println(member));
// 여성 회원만 필터링하여 Set으로 수집
Set<Member> female_members2 = members.stream()
.filter(member -> member.getGender().equals("여"))
.collect(Collectors.toSet());
// 여성 회원 출력
female_members2.stream()
.forEach(member -> System.out.println(member));
// 여성 회원의 이름과 나이를 Map으로 수집
Map<String, Integer> ages = female_members2.stream()
.collect(Collectors.toMap(
member -> member.getName(),
member -> member.getAge()
));
// 이름-나이 맵 출력
System.out.println(ages);