import java.util.stream;
public interface Stream<T> extends BaseStream<T,Stream<T>>{
Stream<T> filter(Predicate<? super T> predicate)
<R> Stream<R> map(Function<? super T,? extends R> mapper);
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
Stream<T> distinct();
Stream<T> limit(long maxSize);
Stream<T> skip(long n);
<R,A> R collect(Collector<? super T,A,R> collector);
<R> R collect(Supplier<R> supplier,BiConsumer<R,? super T> accumulator,BiConsumer<R,R> combiner);
void forEach(Consumer<? super T> action);
long count();
Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity,BinaryOperator<T> accumulator);
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner);
boolean anyMatch(Predicate<? super T> predicate);
boolean allMatch(Predicate<? super T> predicate);
boolean noneMatch(Predicate<? super T> predicate);
// ...
}
- Java8 부터 도입된 기능으로, 컬렉션 데이터를 선언적(선언형 프로그래밍) 방식으로 처리할 수 있게 해주는 API
- 리스트나 배열 같은 데이터를 반복문 없이 간결하게 필터링, 매핑, 정렬, 집계 등의 연산을 수행할 수 있게 됨
• Stream : 데이터 원본(Collection, 배열 등)에 대해 연산을 수행하는 파이프라인
• 중간 연산 : 스트림을 변형하지만 결과를 반환하지 않음(filter, map, sorted등)
• 최종 연산 : 스트림을 소모하고 결과를 반환함(collect, forEach, count, reduce 등)
• 지연 연산 : 최종 연산이 호출되기 전까지 중간 연산은 실행 되지 않음(lazy evaluation)
중간 연산 (Intermediate)
필터링 📌
Stream<T> filter(Predicate<? super T> predicate);
- 조건 필터링
- Predicate : boolean 값을 반환하는 함수형 인터페이스 (test(T t) 메서드 존재)
- 조건을 통과한 요소로 이뤄진 새로운 스트림
- Predicate는 람다식이나 메서드 참조로 전달 가능
Predicate<String> startsWithA = s → s.startsWith(”A”);
names.stream().filter(startsWithA).forEach(System.out::println);
Predicate<Object> p = obj -> obj.toString().length() > 3;
Stream<String> s = Stream.of("hi", "hello", "world");
s.filter(p).forEach(System.out::println); // hello, world
- 스트림의 각 요소에 대해 predicate.test(element)를 호출
- true를 반환하는 요소만 다음 단계로 넘어감
- 최종연산을 호출할 때 실제 실행됨(지연 실행 lazy evaluation)
변환 📌
<R> Stream<R> map(Function<? super T,? extends R> mapper);
- 요소 변환
list.stream().map(String::toUpperCase)
정렬 📌
Stream<T> sorted(); // 자연 순서 정렬(natural order), Comparable 구현 필요
Stream<T> sorted(Comparator<? super T> comparator); // 사용자 지정 기준 정렬
- 정렬
- 호출 당시에는 실제 정렬은 수행되지 않음, 최종 연산을 해야 정렬 결과 평가됨
List<String> names = List.of("Charlie", "Alice", "Bob");
names.stream()
.sorted()
.forEach(System.out::println);
// 출력:
// Alice
// Bob
// Charlie
// 오름차순 정렬
List<Integer> nums = List.of(5, 3, 9, 1);
nums.stream()
.sorted((a, b) -> a - b)
.forEach(System.out::println);
// 또는 Comparator 사용:
nums.stream()
.sorted(Comparator.naturalOrder())
.forEach(System.out::println);
// 내림차순 정렬
nums.stream()
.sorted(Comparator.reverseOrder())
.forEach(System.out::println);
중복 제거 📌
Stream<T> distinct();
- 중복 제거
- equals() 를 기준으로 중복 제거함
자르기 📌
Stream<T> limit(long maxSize);
- 앞에서 최대 maxSize개만 남김
건너뛰기 📌
Stream<T> skip(long n);
- 앞에서 n개 요소를 건너뜀
최종 연산 (Terminal)
<R,A> R collect(Collector<? super T,A,R> collector);
// 사용자 정의 방식으로 수집(병렬 처리 포함)
<R> R collect(Supplier<R> supplier,BiConsumer<R,? super T> accumulator,BiConsumer<R,R> combiner);
- 수집
- Collectors.toList()와 같은 팩토리와 함께 사용하여 결과 수집
list.stream().collect(Collectors.toList());
소비형(Consuing) 연산 📌
void forEach(Consumer<? super T> action);
- 각 요소에 동작
- 순서 보장 ❌
long count();
- 요소 개수 반환
축소(Reduction) 연산 📌
// 요소들을 초기값 없이 누적 처리
Optional<T> reduce(BinaryOperator<T> accumulator);
// 초기값 포함 누적
T reduce(T identity,BinaryOperator<T> accumulator);
// 병렬 처리에 적합한 복잡한 누적 로직 처리
<U> U reduce(U identity,BiFunction<U,? super T,U> accumulator,BinaryOperator<U> combiner);
- 누적 계산
list.stream().reduce((a, b) -> a + b); // 초기값 없이 누적
list.stream().reduce(0, Integer::sum); // 초기값 포함 누적
조건 검사 📌
boolean anyMatch(Predicate<? super T> predicate);
- 하나라도 조건을 만족하면 true
boolean allMatch(Predicate<? super T> predicate);
- 모두 조건을 만족해야 true
boolean noneMatch(Predicate<? super T> predicate);
- 모두 조건을 만족하지 않아야 true
'Java' 카테고리의 다른 글
VO 🆚 DTO (0) | 2025.05.02 |
---|---|
Serializable 인터페이스 (0) | 2025.05.02 |
Predicate 인터페이스 (0) | 2025.05.02 |
참조타입 (reference type) (1) | 2025.05.01 |
기본타입 (primitive type) (0) | 2025.05.01 |