본문 바로가기
프로그래밍언어/JAVA

Java Stream

by 스키피땅콩버터 2021. 3. 15.
반응형

오늘도 정리정리 

Stream은 어떤 것들에 적용할 수 있을까? 

Stream은 주로 Collection, Arrays에서 쓰인다.

 

Stream은 자바 8부터 추가된 기능으로 "컬렉션, 배열등의 저장 요소를 하나씩 참조하며 함수형 인터페이스(람다식)를 적용하며 반복적으로 처리할 수 있도록 해주는 기능"이다. 

(InputStream, OutputStream 같은 I/O Stream이 아니다.)

List<String> names = Arrays.asList("jeong", "pro", "jdk", "java");



// 기존의 코딩 방식

long count = 0;



for (String name : names) {

    if (name.contains("o")) {

        count++;

    }

}

System.out.println("Count : " + count); // 2



// 스트림 이용한 방식

count = 0;

count = names.stream().filter(x -> x.contains("o")).count();

System.out.println("Count : " + count); // 2

출처: https://jeong-pro.tistory.com/165 [기본기를 쌓는 정아마추어 코딩블로그]

스트림을 이용하면 한 줄의 코딩만으로 count값을 구할 수 있다. (count 선언, 출력을 제외하면.)

즉, 불필요한 코딩(for, if 문법)을 걷어낼 수 있고 직관적이기 때문에 가독성이 좋아진다.

이 점이 Stream의 장점이자 목적이다.

 

스트림은 중간처리와 최종 처리를 할  수 있다.

- 중간처리에서는 매핑, 필터링, 정렬을 수행하고 최종 처리에서는 반복, 카운팅, 평균, 총합 등의 집계처리를 수행할 수 있다.

 

 

*알아두기!

  • Stream은 재사용이 불가능하다.
// Stream 재사용 불가 stream has already been operated upon or closed.

Stream<String> a = names.stream().filter(x -> x.contains("o"));



count = a.count();



List<String> lists = a.collect(Collectors.toList());

 

  • 병렬 스트림은 스레드가 작업한다.
names.parallelStream().filter(x -> x.contains("o")).count();

 

 

Stream()으로 스트림을 생성하지 않고 위처럼 parallelStream()으로 병렬 스트림을 만들 수 있다.

이렇게 하면 여러 스레드가 스트림에서 요소를 필터링하고 나온 요소 수를 계산하고 스레드끼리 다시 한번 각자 계산한 count 값들을 더해서 리턴해준다.

단순하게 생각하면 여러스레드가 처리해주니 병렬스트림이 항상 성능면에서 유리해보일 수 있지만 애플리케이션에서 사용하는 쓰레드가 많거나 스트림의 요소 수가 많지 않다면 오히려 스레드를 사용하는데 드는 오버헤드가 더 클 수도 있다.

 

  • 중개 연산은 미리 하지 않는다 지연 연산을 한다.
Stream<String> a = names.stream().filter(x -> x.contains("o")).map(x-> x.concat("s"));

a.forEach(x -> System.out.println(x));

 

위와 같은 코드가 있으면 위에 filter와 map 함수는 미리 계산하고 있지 않고 있다가 forEach와 같은 최종 연산이 적용될 때 중개 연산도 실행된다.

이로써 얻는 장점은 미리 계산하면서 두 번 순회하는 짓을 안 할 수 있게 된다는 점이다.