ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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
      }
    
    }
    반응형

    댓글

Designed by Tistory.