개발 이론/JAVA

Stream

jeonghoe21 2025. 2. 2. 02:31

Chapter 1: Stream 개요

Stream이란?

Stream은 컬렉션, 배열 등의 데이터 소스를 처리하는 기능을 제공하는 Java 8에서 도입된 기능입니다. 내부 반복을 사용하여 데이터의 요소를 효율적으로 처리할 수 있도록 도와줍니다.

Stream의 특징

  • 데이터를 변경하지 않음: 기존 데이터를 변경하지 않고 새로운 스트림을 생성하여 처리함
  • 내부 반복 사용: 루프를 개발자가 직접 제어하지 않고, 스트림 내부에서 처리함
  • 함수형 스타일 코드: map, filter, reduce 등의 함수를 이용하여 직관적으로 코드를 작성할 수 있음
  • 지연 연산 지원: 최종 연산이 실행되기 전까지 중간 연산이 실행되지 않음

Stream의 생성

컬렉션, 배열, 파일, 숫자 범위 등의 데이터 소스로부터 스트림을 생성할 수 있음

import java.util.*;
import java.util.stream.*;

List<String> list = Arrays.asList("Apple", "Banana", "Cherry");
Stream<String> stream = list.stream();

배열을 스트림으로 변환

String[] array = {"Java", "Python", "C++"};
Stream<String> streamFromArray = Arrays.stream(array);

숫자 범위 스트림 생성

IntStream rangeStream = IntStream.range(1, 5); // 1, 2, 3, 4
IntStream rangeClosedStream = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5

파일을 스트림으로 변환

import java.nio.file.*;
import java.io.*;

Stream<String> fileStream = Files.lines(Paths.get("test.txt"));

Chapter 2: Stream의 중간 연산 (Intermediate Operations)

중간 연산은 스트림을 변환하지만 최종 연산이 실행될 때까지 처리되지 않는 특징이 있음 (지연 연산)

filter()

조건에 맞는 요소만 걸러내는 연산

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream().filter(n -> n % 2 == 0).forEach(System.out::println); // 2, 4, 6

map()

각 요소를 변환하는 연산

List<String> words = Arrays.asList("java", "stream", "example");
words.stream().map(String::toUpperCase).forEach(System.out::println);

sorted()

정렬된 스트림을 반환

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 3);
numbers.stream().sorted().forEach(System.out::println); // 1, 2, 3, 5, 8

distinct()

중복을 제거하는 연산

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

limit(), skip()

요소를 제한하거나 건너뛰는 연산

IntStream.range(1, 10).limit(5).forEach(System.out::print); // 12345
IntStream.range(1, 10).skip(5).forEach(System.out::print); // 6789

Chapter 3: Stream의 최종 연산 (Terminal Operations)

최종 연산은 스트림의 요소를 소비하며, 스트림을 닫는 역할을 함

forEach()

각 요소를 소비하는 연산

List<String> list = Arrays.asList("A", "B", "C");
list.stream().forEach(System.out::println);

collect()

스트림을 리스트, 집합 등으로 변환

List<String> collected = Stream.of("a", "b", "c").collect(Collectors.toList());

count()

요소의 개수를 반환

long count = Stream.of(1, 2, 3, 4).count();

reduce()

모든 요소를 하나의 결과값으로 줄이는 연산

int sum = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);

allMatch(), anyMatch(), noneMatch()

조건을 만족하는지 검사하는 연산

boolean allEven = Stream.of(2, 4, 6).allMatch(n -> n % 2 == 0); // true
boolean anyEven = Stream.of(1, 3, 5, 6).anyMatch(n -> n % 2 == 0); // true
boolean noneEven = Stream.of(1, 3, 5).noneMatch(n -> n % 2 == 0); // true

Chapter 4: 병렬 스트림 (Parallel Stream)

스트림을 병렬로 처리하여 성능을 향상시킬 수 있음

병렬 스트림 사용법

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.parallelStream().forEach(System.out::println);

병렬 스트림의 주의점

  • 데이터 순서가 중요할 경우 forEachOrdered()를 사용
numbers.parallelStream().forEachOrdered(System.out::println);
  • 병렬 처리는 성능 이점을 제공하지만, 작은 데이터에서는 오버헤드가 발생할 수 있음

Chapter 5: Stream 활용 예제

문자열 리스트에서 특정 길이 이상의 문자열 필터링

List<String> words = Arrays.asList("apple", "banana", "cherry", "date");
List<String> filtered = words.stream()
                             .filter(word -> word.length() > 5)
                             .collect(Collectors.toList());
System.out.println(filtered);

숫자 리스트의 평균값 계산

List<Integer> numbers = Arrays.asList(10, 20, 30, 40, 50);
double average = numbers.stream().mapToInt(n -> n).average().orElse(0);
System.out.println(average);

Map에서 키 값 추출

Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
map.keySet().stream().forEach(System.out::println);

이와 같이 Stream API를 사용하면 데이터를 보다 쉽게 변환하고 가공할 수 있습니다.

'개발 이론 > JAVA' 카테고리의 다른 글

Lambda  (0) 2025.03.04
Collection  (0) 2025.02.02
상속  (0) 2025.02.01
객체지향이란?  (0) 2025.02.01
배열  (0) 2025.02.01