-
Java8. 스트림 (Stream)BackEnd/Java 2022. 1. 22. 06:29반응형
스트림(Stream)이란 순차 또는 병렬 집계 작업을 지원하는 오퍼레이션들의 모음입니다(Sequence of elements supporting sequential and parallel aggregate operations).
스트림의 특징
- 데이터를 담고 있는 저장소(Collection)가 아닙니다.
- Functional in nature, 스트림이 처리하는 데이터 소스를 변경하지 않습니다.
- 스트림으로 처리하는 데이터는 오직 한 번만 처리됩니다.
- 무제한일 수도 있습니다. (Short Circuit 메소드를 사용해서 제한할 수 있습니다.)
- 중개 오퍼레이션은 근본적으로 lazy 합니다. (lazy하다는 것은 종료 오퍼레이션이 오기 전까지 실행되지 않는 것을 의미합니다.)
- 손쉽게 병렬 처리할 수 있습니다. (단, 쓰레드 생성 및 컨텍스트 스위치 비용으로 무조건 병렬 처리가 빠르지는 않습니다.)
스트림 파이프라인
- 0 또는 다수의 중개 오퍼레이션과 한 개의 종료 오퍼레이션으로 구성합니다.
- 스트림의 데이터 소스는 오직 종료 오퍼레이션을 실행할 때만 처리합니다.
중개 오퍼레이션 (Intermediate operation)
filter, map, limit, skip, sorted 등 Stream을 리턴합니다.
종료 오퍼레이션 (Terminal operation)
collect, allMatch, count, forEach, min, max 등 Stream을 리턴하지 않습니다.
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class StreamBasic { public static void main(String[] args) { List<String> stream = new ArrayList<>(); stream.add("Ballantines"); stream.add("Macallan"); stream.add("Royal Salute"); stream.add("Scotch Blue"); stream.add("Johnnie Walker"); // 모든 문자를 대문자로 변환합니다. Stream<String> stringStream = stream.stream().map(String::toUpperCase); System.out.println("=================[Functional in nature]================="); System.out.println("=== 기존 데이터 소스를 변경하지 않습니다.==="); stream.forEach(System.out::println); System.out.println("===모든 문자를 대문자로 변환합니다.==="); stringStream.forEach(System.out::println); System.out.println("========================================================"); System.out.println("=========================[lazy]========================="); Stream<String> lazyStream = stream.stream().map((s) -> { System.out.println("중개 오퍼레이션: " + s); return s.toLowerCase(); }); System.out.println("===종료 오퍼레이션 이후 실행됩니다.==="); lazyStream.forEach(System.out::println); System.out.println("========================================================"); System.out.println("================[병렬 처리 (parallelStream)]==============="); System.out.println("===병렬처리 시 처리하는 Thread를 출력하고, 모든 문자를 소문자로 출력합니다.==="); List<String> collect = stream.parallelStream().map((s) -> { System.out.println(s + " " + Thread.currentThread().getName()); return s.toLowerCase(); }).collect(Collectors.toList()); System.out.println("===모든 문자를 소문자로 변환합니다.==="); collect.forEach(System.out::println); System.out.println("========================================================"); } } /******************************************************* [결과] =================[Functional in nature]================= === 기존 데이터 소스를 변경하지 않습니다.=== Ballantines Macallan Royal Salute Scotch Blue Johnnie Walker ===모든 문자를 대문자로 변환합니다.=== BALLANTINES MACALLAN ROYAL SALUTE SCOTCH BLUE JOHNNIE WALKER ======================================================== =========================[lazy]========================= ===종료 오퍼레이션 이후 실행됩니다.=== 중개 오퍼레이션: Ballantines ballantines 중개 오퍼레이션: Macallan macallan 중개 오퍼레이션: Royal Salute royal salute 중개 오퍼레이션: Scotch Blue scotch blue 중개 오퍼레이션: Johnnie Walker johnnie walker ======================================================== ================[병렬 처리 (parallelStream)]=============== ===병렬처리 시 처리하는 Thread를 출력하고, 모든 문자를 소문자로 출력합니다.=== Ballantines ForkJoinPool.commonPool-worker-23 Macallan ForkJoinPool.commonPool-worker-19 Royal Salute main Johnnie Walker ForkJoinPool.commonPool-worker-5 Scotch Blue ForkJoinPool.commonPool-worker-9 ===모든 문자를 소문자로 변환합니다.=== ballantines macallan royal salute scotch blue johnnie walker ======================================================== *******************************************************/
Stream API
스트림 생성 (Iterate)
import java.util.stream.Stream; public class StreamAPI { public static void main(String[] args) { // 1부터 1씩 증가하는 무제한 숫자 스트림에서 5개를 skip하고 최대 5개를 가져온다. Stream.iterate(1, i -> i + 1) .skip(5) .limit(5) .forEach(System.out::println); // [결과] 6 7 8 9 10 } }
스트림 필터 (Filter)
public class Person { private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
import java.util.ArrayList; import java.util.List; public class StreamAPI { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person(6, "Daol")); list.add(new Person(4, "Iden")); list.add(new Person(3, "Jena")); // Filter(Predicate) // 이름이 "D"로 시작하는 Person 필터링 list.stream() .filter(s -> s.getName().startsWith("D")) .forEach(s -> System.out.println(s.getName())); // [결과]: Daol } }
스트림 변경 (Map / FlatMap)
import java.util.ArrayList; import java.util.Collection; import java.util.List; public class StreamAPI { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person(6, "Daol")); list.add(new Person(4, "Iden")); list.add(new Person(3, "Jena")); // Map(Function) // Person에서 String name만 새로운 스트림으로 반환합니다. list.stream() .map(Person::getName) .forEach(System.out::println); // [결과]: Daol Iden Jena // FlatMap(Function) // 신규 list를 생성합니다. List<Person> newList = new ArrayList<>(); newList.add(new Person(35, "Hanseom")); // list를 담고 있는 flatMapList 생성합니다. List<List<Person>> flatMapList = new ArrayList<>(); flatMapList.add(list); flatMapList.add(newList); // 모든 원소(list / newList)를 단일 원소로 변환합니다. flatMapList.stream() .flatMap(Collection::stream) .forEach(s -> System.out.println(s.getName())); // [결과]: Daol Iden Jena Hanseom } }
스트림 검사 (anyMatch() / allMatch() / nonMatch())
import java.util.ArrayList; import java.util.List; public class StreamAPI { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person(6, "Daol")); list.add(new Person(4, "Iden")); list.add(new Person(3, "Jena")); // 이름 중에 "a"가 포함된 문자열이 있는지 확인합니다. boolean bool = list.stream() .anyMatch(s -> s.getName().contains("l")); System.out.println(bool); // [결과]: true } }
스트림 집계 (collect() / sum() / max() / count())
import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class StreamAPI { public static void main(String[] args) { List<Person> list = new ArrayList<>(); list.add(new Person(6, "Daol")); list.add(new Person(4, "Iden")); list.add(new Person(3, "Jena")); // 이름에 "a"가 포함된 새로운 list를 만듭니다. List<String> aList = list.stream().filter(s -> s.getName().contains("a")) .map(Person::getName) .collect(Collectors.toList()); aList.forEach(System.out::println); // [결과]: Daol, Jena } }
반응형'BackEnd > Java' 카테고리의 다른 글
Java8. Date-Time API (0) 2022.01.22 Java8. Optional (0) 2022.01.22 Java8. 기본 메소드 (Default Method)와 스태틱 메소드 (Static Method) (0) 2022.01.22 Java8. 메소드 레퍼런스 (Method Reference) (0) 2022.01.20 Java8. 람다 표현식 (Lambda Expressions) (0) 2022.01.20