inblog logo
|
DailyCoding
    Spring Boot

    10-7. Stream API

    박은서's avatar
    박은서
    Feb 06, 2026
    10-7. Stream API
    Contents
    1️⃣ Stream이란? (Java 기준)2️⃣ Stream 처리 구조3️⃣ 자주 쓰이는 중간 연산 함수4️⃣ 자주 쓰이는 최종 연산 함수5️⃣ Stream 사용 시 자주 하는 패턴6️⃣ Stream 사용 시 주의점7️⃣ 실습

    1️⃣ Stream이란? (Java 기준)

    1) 개념

    컬렉션(또는 배열)의 데이터를 선언형으로 처리하기 위한 데이터 처리 파이프라인

    2) 핵심 개념 요약

    • 데이터 저장 X → Stream은 데이터를 보관하지 않음
    • 함수형 처리 → filter, map 같은 함수 조합
    • 지연 연산(Lazy) → 최종 연산이 호출될 때까지 실행 안 됨
    • 1회용 → 한 번 사용하면 재사용 불가
    • 병렬 처리 가능 → parallelStream()
    List<Integer> numbers = List.of(1, 2, 3, 4, 5); numbers.stream() .filter(n -> n % 2 == 0) .map(n -> n * 10) .forEach(System.out::println);

    2️⃣ Stream 처리 구조

    데이터 소스 ↓ 중간 연산 (0개 이상) ↓ 최종 연산 (1개, 필수)
    구분
    특징
    중간 연산
    Stream 반환 (체이닝 가능)
    최종 연산
    결과 반환 또는 실행 후 종료

    3️⃣ 자주 쓰이는 중간 연산 함수

    1) filter(Predicate)

    조건에 맞는 요소만 통과
    stream.filter(x -> x > 10)
    ✔ Boolean 반환 함수 사용

    2) map(Function)

    요소를 다른 형태로 변환
    stream.map(String::length)
    ✔ 1 → 1 변환

    3) flatMap(Function)

    중첩 구조를 평탄화
    List<List<Integer>> list = List.of( List.of(1, 2), List.of(3, 4) ); list.stream() .flatMap(List::stream) .forEach(System.out::println);
    ✔ List<List<T>> → Stream<T>

    4) distinct()

    중복 제거 (equals 기준)
    stream.distinct()

    5) sorted() / sorted(Comparator)

    정렬
    stream.sorted() stream.sorted(Comparator.reverseOrder())

    6) limit(n) / skip(n)

    개수 제한 / 건너뛰기
    stream.limit(5) stream.skip(3)

    4️⃣ 자주 쓰이는 최종 연산 함수

    1) forEach(Consumer)

    각 요소에 대해 동작 수행
    stream.forEach(System.out::println);
    ⚠ 반환값 없음

    2) collect(Collector)

    Stream → 컬렉션 변환
    List<String> result = stream.collect(Collectors.toList());
    자주 쓰는 예:
    Collectors.toSet() Collectors.toMap(k -> k.getId(), v -> v) Collectors.joining(", ")

    3) reduce(BinaryOperator)

    요소를 하나의 값으로 축소
    int sum = stream.reduce(0, Integer::sum);

    4) count()

    요소 개수
    long cnt = stream.count();

    5) anyMatch / allMatch / noneMatch

    조건 검사
    stream.anyMatch(x -> x > 100); stream.allMatch(x -> x > 0); stream.noneMatch(x -> x < 0);

    6) findFirst() / findAny()

    요소 하나 찾기 (Optional 반환)
    Optional<Integer> value = stream.findFirst();

    5️⃣ Stream 사용 시 자주 하는 패턴

    1) 컬렉션 필터링 + 변환

    List<String> names = users.stream() .filter(u -> u.isActive()) .map(User::getName) .toList();

    2) 합계 / 평균

    int total = orders.stream() .mapToInt(Order::getPrice) .sum();

    3) 그룹핑

    Map<String, List<User>> byRole = users.stream() .collect(Collectors.groupingBy(User::getRole));

    6️⃣ Stream 사용 시 주의점

    1) ⚠️ 부작용(side effect) 최소화

    // ❌ 지양 stream.forEach(x -> list.add(x));

    2) ⚠️ Stream 재사용 불가

    Stream<Integer> s = list.stream(); s.count(); s.forEach(...); // 예외 발생

    3) ⚠️ 단순 반복은 for-loop이 더 명확한 경우도 있음

    7️⃣ 실습

    1) 가공

    C:\workspace\spring_lab\skillapp\src\main\java\ex04\StreamEx01.java
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 1. 가공 List<Integer> newList = list.stream() // 개울에 던지기 .map(i -> i * 2) // 가공 or 연산 (N번) : 중간 연산 .toList(); // 수집 // for문으로 출력 newList.stream().forEach(i -> { System.out.println(i); }); } }
    notion image
    💡
    Stream은 중간 연산을 여러 번 할 수 있다!

    2) 필터

    C:\workspace\spring_lab\skillapp\src\main\java\ex04\StreamEx01.java
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 2. filter List<Integer> newList2 = list.stream() .map(i -> i+1) .peek(i -> System.out.println(i)) // 한 줄만 적으면 중괄호도 생략 가능 .filter(i -> i < 3) .toList(); } }
    notion image
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 2. filter List<Integer> newList2 = list.stream() .map(i -> i+1) .peek(i -> System.out.println(i)) // 한 줄만 적으면 중괄호도 생략 가능 .filter(i -> i < 3) .peek(i -> System.out.println(i)) // 두번째 peek만 작동 .toList(); } }
    notion image
    💡
    peek 은 중간과정 확인용!!
    확인했으면 주석처리
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 2. filter List<Integer> newList2 = list.stream() .map(i -> i+1) .peek(i -> System.out.print(i + " ")) // 한 줄만 적으면 중괄호도 생략 가능 .filter(i -> i < 3) .toList(); System.out.println(); for (Integer i : newList2) { System.out.print(i + " "); } } }
    notion image

    3) Max

    C:\workspace\spring_lab\skillapp\src\main\java\ex04\StreamEx01.java
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 3. Max int maxNum = list.stream() .mapToInt(i -> i) .max() .getAsInt(); System.out.println(maxNum); } }
    notion image

    4) limit

    C:\workspace\spring_lab\skillapp\src\main\java\ex04\StreamEx01.java
    package ex04; import java.util.List; /** * Stream : 임시 개울 (임시 수도관) */ public class StreamEx01 { public static void main(String[] args) { List<Integer> list = List.of(1, 2, 3, 4); // 4. limit List<Integer> newList4 = list.stream() .limit(2) .peek(i -> System.out.print(i + " ")) .toList(); } }
    notion image

    5) flatMap

    C:\workspace\spring_lab\skillapp\src\main\java\ex04\StreamEx02.java
    package ex04; import java.util.List; public class StreamEx02 { public static void main(String[] args) { // [ [1, 2, 3] , [4, 5] , [6, 7, 8, 9] ] List<List<Integer>> matrix = List.of( List.of(1, 2, 3), List.of(4, 5), List.of(6, 7, 8, 9) ); // [ [1,2,3], [4,5], [6,7,8,9] ] // [1,2,3], [4,5], [6,7,8,9] // 1,2,3 4,5 6,7,8,9 // 1,2,3,4,5,6,7,8,9 // [1,2,3,4,5,6,7,8,9] List<Integer> newList = matrix.stream() .flatMap(list -> list.stream()) .toList(); for (Integer i : newList){ System.out.print(i + " "); } } }
    notion image
    package ex04; import java.util.List; public class StreamEx02 { public static void main(String[] args) { // [ [1, 2, 3] , [4, 5] , [6, 7, 8, 9] ] List<List<Integer>> matrix = List.of( List.of(1, 2, 3), List.of(4, 5), List.of(6, 7, 8, 9) ); // [ [1,2,3], [4,5], [6,7,8,9] ] // [1,2,3], [4,5], [6,7,8,9] // 1,2,3 4,5 6,7,8,9 // 1,2,3,4,5,6,7,8,9 // [1,2,3,4,5,6,7,8,9] List<Integer> newList = matrix.stream() .flatMap(list -> list.stream()) .filter(i -> i > 5) .toList(); for (Integer i : newList){ System.out.print(i + " "); } } }
    notion image

    6) 적용

    C:\workspace\spring_lab\skillapp\src\main\java\ex01\CopyEx04.java
    package ex01; import lombok.Data; import java.util.ArrayList; import java.util.List; @Data class Board { // 1:N의 관계에서 Board가 1 private int id; private String title; private String content; private List<Reply> replies = new ArrayList<>(); } @Data class Reply { // 1:N의 관계에서 Reply는 N private int id; private String comment; } @Data class DetailDTO { private int id; private String title; private String content; private List<String> comments = new ArrayList<>(); public DetailDTO(Board board) { this.id = board.getId(); this.title = board.getTitle(); this.content = board.getTitle(); this.comments = board.getReplies().stream() .map(i -> i.getComment()) .limit(2) .toList(); // for (int i = 0; i < board.getReplies().size(); i++) { // this.comments.add(board.getReplies().get(i).getComment()); // } // for문은 복잡! stream이 보기 편함! -> 그래서 stream 배울 것 // for (Reply reply : board.getReplies()) { // // if (id < 3) // if (reply.getId() < 3) { // this.comments.add(reply.getComment()); // } // // this.comments.add(reply.getComment()); // } } } public class CopyEx04 { public static void main(String[] args) { // 3. 클래스로 넘기기 Reply r1 = new Reply(); r1.setId(1); r1.setComment("댓글1"); Reply r2 = new Reply(); r2.setId(2); r2.setComment("댓글2"); Reply r3 = new Reply(); r3.setId(3); r3.setComment("댓글3"); Board board = new Board(); board.setId(1); board.setTitle("제목1"); board.setContent("내용1"); board.setReplies(List.of(r1, r2, r3)); DetailDTO detailDTO = new DetailDTO(board); System.out.println(detailDTO); } }
    notion image
    Share article
    Contents
    1️⃣ Stream이란? (Java 기준)2️⃣ Stream 처리 구조3️⃣ 자주 쓰이는 중간 연산 함수4️⃣ 자주 쓰이는 최종 연산 함수5️⃣ Stream 사용 시 자주 하는 패턴6️⃣ Stream 사용 시 주의점7️⃣ 실습

    DailyCoding

    RSS·Powered by Inblog