본문 바로가기

자바

Java Stream

Stream이란

(1) Stream?

Stream이란, 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소이다.

  • Stream은 순차적으로 혹은 병렬적으로 실행하여 데이터를 처리할 수 있다.
  • Stream은 Collection, 배열, I/O 자원 등의 데이터 제공 소스로부터 데이터를 소비한다.
  • Stream은 Collection과 마찬가지로, 특정 요소 형식으로 이루어진 연속된 값 집합 인터페이스를 제공한다. Collection의 경우 요소의 저장 및 접근 연산 중심이며, Stream의 경우에는 filter, sorted, map, distinct과 같은 데이터 처리 중심이다.

(2) Stream 특징

1.Stream은 수직적으로(위에서 아래로) 동작한다.

arr.stream()
  .filter(...)
  .map(...)
  .findFirst();
  • filter -> map -> findFirst 순으로 동작한다.

2.Stream은 재사용이 불가능하다.

Stream<String> stream = Stream.of("GilSSang", "Tommo", "Dolphin").filter(name -> name.contains("o"));

Optional<String> firstTry = stream.findFirst();
Optional<String> secondTry = stream.findAny(); // IllegalStateException: stream has already been operated upon or closed
  • Stream을 한 번 소비하고 난 뒤, 그 이후에 재사용할 수 없다.

3.Stream은 내부 반복을 지원한다.

  • Collection은 외부 반복을 지원하기에 for 구문을 통해 사용자가 직접 처리해야한다.
  • Stream은 내부 반복을 지원하기에 반복을 알아서 처리하기에 반복자를 사용할 필요가 없으며 병렬성 구현을 자동으로 선택구현할 수 있다.

4.Stream은 늦은 처리(Lazy Invocation)를 지원한다.

public class CollectionStream {
    public static int length(String s) {
        System.out.println(s + " length : " + s.length());
        return s.length();
    }

    public static String substr(String s) {
        System.out.println(s + " substr : " + s.substring(0, 3));
        return s.substring(0, 3);
    }

    public static void main(String[] args) {
        System.out.println("------------------");
        ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));
        Stream<String> stream = arr.stream()
                .filter(name -> length(name) > 5)
                .map(name -> substr(name));
        System.out.println("Stream Created");
        List<String> list = stream.collect(Collectors.toList());
        System.out.println("list : " + list);
        System.out.println("------------------");
    }
}
------------------
Stream Created
GilSSang length : 8
GilSSang substr : Gil
Tommo length : 5
Dolphin length : 7
Dolphin substr : Dol
firstLength : [Gil, Dol]
------------------

Process finished with exit code 0
  • Stream은 최종 연산을 진행하기 전에 중간 연산을 실행하지 않는다.

  • Stream은 연산을 최대한 지연(Lazy)시켜 프로그램 성능의 향상을 도모한다.

Stream 생성

(1) 배열을 통해 Stream 생성

String[] arr = new String[]{"GilSSang", "Tommo", "Dolphin"};
Stream<String> stream = Arrays.stream(arr);
  • 간단하게 Arrays.stream()메소드를 통해 생성할 수 있다.

(2) 컬렉션을 통해 Stream 생성

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));
Stream<String> stream = arr.stream();
  • 컬렉션 타입의 경우 인터페이스에 추가된 디포릍 메소드 stream()을 통해 생성할 수 있다.

Stream 연산

(1) 중간 연산

1.filter

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));
Stream<String> stream = arr.stream()
        .filter(name -> name.length() > 5);

// ["GilSSang", "Dolphin"]
  • 필터(filter)는 스트림 내 요소들을 지정한 람다식을 기반으로 하나씩 평가해서 걸러내는 작업을 진행한다.

2.map

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));
Stream<String> stream = arr.stream()
        .map(name -> name.substring(0, 3));

// [Gil, Tom, Dol]
  • 맵(map)은 스트림 내 요소들을 하나씩 지정한 람다식에 적용하여 값을 변환해준다.

3.sorted

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));Stream<String> stream = arr.stream()        .sorted();// [Dolphin, GilSSang, Tommo]ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));Stream<String> stream = arr.stream()        .sorted(Comparator.reverseOrder());// [Tommo, GilSSang, Dolphin]
  • 정렬(sort)은 스트림 내 요소들을 Comparator를 이용하여 정렬을 진행한다.

4.distinct

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "GilSSang", "Tommo", "Dolphin"));Stream<String> stream = arr.stream()        .distinct();
  • 중복제거(distinct)은 스트림 내 요소들의 중복 요소들을 제거해준다.

(2) 최종 연산

1.forEach

스트림에서 작업한 결과를 소비하여 결과를 반환한다.

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));arr.stream()        .map(name -> name.substring(0, 3))        .forEach(System.out::println);
  • forEach를 사용하여 스트림에서 작업한 결과를 출력했다.

2.collect

Collector타입의 인자를 받아서 처리한다.

ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));List<String> list = arr.stream()        .map(name -> name.substring(0, 3))        .collect(Collectors.toList());// [Gil, Tom, Dol]
  • 스트림에서 작업한 결과를 담은 리스트로 반환한다.
ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));String s = arr.stream()        .map(name -> name.substring(0, 3))        .collect(Collectors.joining());// GilTomDol
  • 스트림에서 작업한 결과를 문자열로 이어 반환한다.
ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));Integer sum = arr.stream()        .map(name -> name.substring(0, 3))        .collect(Collectors.summingInt(String::length));// 9
  • 스트림에서 작업한 결과 입력받은 메소드 기반으로 총합을 구한다.
ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));Integer sum = arr.stream()        .map(name -> name.substring(0, 3))        .collect(Collectors.averageingInt(String::length));// 3
  • 스트림에서 작업한 결과를 입력받은 메소드 기반으로 평균을 구한다.
ArrayList<String> arr = new ArrayList<>(Arrays.asList("GilSSang", "Tommo", "Dolphin"));IntSummaryStatistics collect = arr.stream()        .map(name -> name.substring(0, 3))        .collect(Collectors.summarizingInt(String::length));System.out.println("collect = " + collect);// IntSummaryStatistics{count=3, sum=9, min=3, average=3.000000, max=3}
  • 스트림에서 작업한 결과를 입력받은 메소드 기반으로 전체적인 Summary를 구한다.

3.count

ArrayList<Integer> arr = new ArrayList<>(Arrays.asList(1, 2, 3));long count = arr.stream()        .count();
  • 스트림에서 작업한 결과의 수를 반환한다.

'자바' 카테고리의 다른 글

JAVA Collection  (0) 2021.10.15
JAVA Lambda, Functional Interface  (0) 2021.10.14
JAVA Exception  (0) 2021.10.13
Java Optional  (1) 2021.10.04
JVM, JRE, JDK  (0) 2021.09.18