BE/Java

[Java] 스트림

baek-dev 2024. 12. 9. 18:53

1.  스트림

스트림은 컬렉션이나 배열같은 데이터 소스를 처리하기 위한 강력하고 선언적인 방식이다

데이터 처리 파이프라인을 만들도록 돕는 기능

  • 데이터 저장소가 아니라 데이터의 흐름
  • 원본데이터를 변경하지 않음
  • 선언형
  • 파이프라인 방식으로 연속적 작업을 연결

 

2. 핵심 구성 요소

  • 중간연산 : 스트림을 변환하는 작업 (filter, map, sorted 등)
  • 종결 연산 : 스트림을 소모하여 최종 결과를 반환 (forEach, collect, reduce 등)

 

3. 특징

  • 1회성 사용 : 한번 사용하면 재사용할 수 없다
  • 게으른 연산 : 중간 연산은 결과가 필요할때까지 실행되지 않는다
  • 병렬처리 지원 : parallelStream() 을 통해 병렬 처리가 가능하다

 

4. 장점

  • 코드 간결화
  • 병렬 처리
  • 함수형 스타일

 

5. 예제

List<String> words = Arrays.asList("apple", "cat", "banana", "dog");
List<String> result = words.stream()
                           .filter(word -> word.length() >= 3)
                           .map(String::toUpperCase)
                           .sorted()
                           .collect(Collectors.toList());
// 결과: ["APPLE", "BANANA", "DOG"]

 

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
int sum = numbers.stream()
                 .filter(n -> n % 2 == 0)
                 .reduce(0, Integer::sum);
// 결과: 12

사용법

1. 스트림 생성 메서드

1.1. 컬렉션

List<String> list = Arrays.asList("A", "B", "C");
Stream<String> stream = list.stream(); // 순차 스트림
Stream<String> parallelStream = list.parallelStream(); // 병렬 스트림

1.2. 배열

String[] array = {"A", "B", "C"};
Stream<String> stream = Arrays.stream(array);

1.3. 범위지정

IntStream intStream = IntStream.range(1,5);	// 1,2,3,4
IntStream closeStream = IntStream.rangeClosed(1,5);	// 1,2,3,4,5

1.4. Stream.builder()

Stream<String> stream = Stream.<String>builder()
                              .add("A").add("B").add("C")
                              .build();

1.5. 무한스트림

  • Stream.iterate
Stream<Integer> stream = Stream.iterate(1, n -> n + 1).limit(10);
// 결과: 1, 2, 3, ..., 10
  • Stream.generate
Stream<Double> stream = Stream.generate(Math::random).limit(5);
// 결과: 무작위 숫자 5개

2. 중간 연산 메서드

2.1. filter()

특정 조건을 만족한 요소만 남김

List<String> list = Arrays.asList("apple", "banana", "cherry");
List<String> filtered = list.stream()
                            .filter(s -> s.startsWith("a"))
                            .collect(Collectors.toList());
// 결과: ["apple"]

 

2.2. map()

요소를 다른 형태로 변환

List<String> names = Arrays.asList("Alice", "Bob");
List<Integer> lengths = names.stream()
                             .map(String::length)
                             .collect(Collectors.toList());
// 결과: [5, 3]

2.3. flatMap()

중첩된 구조를 단일 스트림으로 변환

List<List<String>> nestedList = Arrays.asList(
    Arrays.asList("A", "B"),
    Arrays.asList("C", "D")
);
List<String> flattened = nestedList.stream()
                                   .flatMap(List::stream)
                                   .collect(Collectors.toList());
// 결과: ["A", "B", "C", "D"]

2.4. distinct()

중복을 제거

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 4, 4);
List<Integer> distinctNumbers = numbers.stream()
                                       .distinct()
                                       .collect(Collectors.toList());
// 결과: [1, 2, 3, 4]

2.5. sorted()

정렬

List<String> names = Arrays.asList("Bob", "Alice", "Charlie");
List<String> sorted = names.stream()
                           .sorted()
                           .collect(Collectors.toList());
// 결과: ["Alice", "Bob", "Charlie"]
List<String> reversed = names.stream()
                             .sorted(Comparator.reverseOrder())
                             .collect(Collectors.toList());
// 결과: ["Charlie", "Bob", "Alice"]

2.6. limit() & skip()

  • limit : 앞에서 n개만 추출
List<Integer> limited = IntStream.range(1, 10)
                                 .limit(5)
                                 .boxed()
                                 .collect(Collectors.toList());
// 결과: [1, 2, 3, 4, 5]
  • skip : 앞에서 n개 건너뜀
List<Integer> skipped = IntStream.range(1, 10)
                                 .skip(5)
                                 .boxed()
                                 .collect(Collectors.toList());
// 결과: [6, 7, 8, 9]

3. 종결 연산 메서드

3.1. forEach()

모든 요소에 대해 작업 수행

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

3.2. collect()

스트림을 컬렉션으로 변환

  • 리스트로 변환
List<String> list = stream.collect(Collectors.toList());
  • 세트로 변환
Set<String> set = stream.collect(Collectors.toSet());
  • 문자열로 결합
String result = stream.collect(Collectors.joining(", "));
// 결과: "A, B, C"

3.3. reduce()

모든 요소를 하나의 값으로 축약

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
int sum = numbers.stream()
                 .reduce(0, Integer::sum);
// 결과: 10

3.4. count()

스트림의 요소 개수 변환

long count = stream.count();

3.5. anyMatch(), allMatch(), noneMatch()

  • anyMatch : 조건을 만족하는 요소가 있는지 확인
boolean hasEven = IntStream.range(1, 10)
                           .anyMatch(n -> n % 2 == 0);
// 결과: true
  • allMatch : 모든 요소가 조건을 만족하는지 확인
boolean allEven = IntStream.range(2, 10)
                           .allMatch(n -> n % 2 == 0);
// 결과: false
  • noneMatch : 조건을 만족하는 요소가 없는지 확인
boolean noneEven = IntStream.range(1, 10)
                            .noneMatch(n -> n > 10);
// 결과: true

3.6. findFirst() & findAny()

  • findFirst : 첫번째 요소 반환
Optional<Integer> first = IntStream.range(1, 10).findFirst();
  • findAny : 병렬 처리시, 임의의 요소 반환
Optional<Integer> any = IntStream.range(1, 10).findAny();

4. 병렬 스트림

병렬 스트림 생성

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream()
                 .reduce(0, Integer::sum);

 

 

 

 

 

출처 : ChatGPT

'BE > Java' 카테고리의 다른 글

[Java] JDBC와 JPA  (1) 2024.12.11
[Java] 람다식  (0) 2024.12.10
[Java] Map  (0) 2024.12.07
[Java] Optional  (0) 2024.12.06
[Java] List  (1) 2024.12.05