스트림

  • 데이터를 효율적으로 처리할 수 있는 흐름
  • 선언형 스타일로, 가독성 뛰어남
  • 데이터 준비 -> 중간 연산 -> 최종 연산 순으로 처리
  • 컬렉션 (List, Set 등)과 함께 자주 활용

for문 vs 스트림

`arrayList`에 저장한 리스트 데이터를 곱셈 연산한 결과값을 저장하는 과정

// for문
public class Main {
    public static void main(String[] args) {
    
        // ArrayList 선언
        List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));

        // ✅ for 명령형 스타일: 각 요소 * 10 처리
        List<Integer> ret1 = new ArrayList<>();
        for (Integer num : arrayList) {
            int multipliedNum = num * 10; // 각 요소 * 10
            ret1.add(multipliedNum);
        }
        System.out.println("ret1 = " + ret1); 
    }
}
// 스트림
public class Main {
    public static void main(String[] args) {

        // ArrayList 선언
        List<Integer> arrayList = new ArrayList<>(List.of(1, 2, 3, 4, 5));

        // ✅ 스트림 선언적 스타일: 각 요소 * 10 처리
        List<Integer> ret2 = arrayList.stream()
					.map(num -> num * 10)
					.collect(Collectors.toList());
        System.out.println("ret2 = " + ret2);
    }
}

 

☝️ ArrayList를 List 인터페이스로 받는 이유

List 인터페이스로 구현체(ArrayList)를 받으면 나중에 다른 구현체(LinkedList, Vector) 로 변경할 때 코드 수정을 최소화

 


스트림 처리 단계

단계 설명 주요 API
1. 데이터 준비 컬렉션을 스트림으로 변환 `stream()`, `parallelStream()`
2. 중간 연산 등록 (즉시 실행 X) 데이터 변환 및 필터링 `map()`, `filter()`, `sorted()`, `distinct()`
3. 최종 연산 최종 처리 및 데이터 변환 `collect()`, `forEach()`, `count()`, `reduce()`

 


 

스트림 생성 방법

1. 스트림 생성 

// 컬렉션 기반 스트림
List<String> list = Arrays.asList("apple", "banana", "cherry");
Stream<String> stream = list.stream();

// 배열 -> 스트림
String[] arr = {"apple", "banana", "cherry"};
Stream<String> stream = Arrays.stream(arr);

// 여러 값 -> 스트림
Stream<String> stream = Stream.of("apple", "banana", "cherry");
  • stream() : 스트림 생성
  • Stream.of() : 여러 값으로 스트림 직접 생성

 

스트림 중간 연산

  • 스트림 변환 작업
  • 실행 전까지 수행되지 않음

filter() - 조건을 만족하는 요소만 필터링

List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream()
    .filter(s -> s.startsWith("b"))
    .forEach(System.out::println);  // 출력: banana

 

map() - 각 요소를 변환

List<String> list = Arrays.asList("apple", "banana", "cherry");
list.stream()
    .map(String::toUpperCase)
    .forEach(System.out::println);
// 출력: APPLE, BANANA, CHERRY

 

sorted() - 정렬

List<String> list = Arrays.asList("cherry", "banana", "apple");
list.stream()
    .sorted() 			// sorted(Comparator.reverseOrder()) 내림차순 정렬
    .forEach(System.out::println);
// 출력: apple, banana, cherry (오름차순 정렬)

 

distinct() - 중복 제거

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4);
numbers.stream()
    .distinct()
    .forEach(System.out::println);
// 출력: 1, 2, 3, 4

 

limit() - 특정 개수만 출력

Stream.of(1, 2, 3, 4, 5)
    .limit(3)
    .forEach(System.out::println);
// 출력: 1, 2, 3

 

skip() - 앞에서 n개 요소 건너뛰기

Stream.of(1, 2, 3, 4, 5)
    .skip(2)
    .forEach(System.out::println);
// 출력: 3, 4, 5

 


 

스트림 최종 연산

  • 결과 반환하는 연산

forEach() - 모든 요소 처리

Stream.of("apple", "banana", "cherry")
    .forEach(System.out::println);

 

collect() - 결과를 컬렉션으로 변환

List<String> list = Stream.of("apple", "banana", "cherry")
    .collect(Collectors.toList());

2025.03.07 - [언어/Java] - Collectors 클래스

 

count() - 요소 개수 반환

long count = Stream.of(1, 2, 3, 4, 5)
    .count();
System.out.println(count);  // 출력: 5

 

reduce() - 요소를 누적하여 결과 반환

int sum = Stream.of(1, 2, 3, 4, 5)
    .reduce(0, Integer::sum);      // 초기값 0
System.out.println(sum);  // 출력: 15

 

 


병렬 스트림 (Parallel Stream)

  • 스트림은 기본적으로 순차적으로 처리
  • 병렬 스트림을 사용하면 멀티코어 CPU를 활용한 병렬 처리 가능
  • 병렬로 실행되므로 출력 순서 일정하지 않을 수 있음
List<String> list = Arrays.asList("apple", "banana", "cherry");
list.parallelStream()
    .forEach(System.out::println);