Java Stream API

Lee Seung Jae·2021년 4월 2일

Java Stream API

Java Stream

Java를 다시 공부하면서 Java8에 추가된 기능중 Stream이라는 API의 기능이 있었지만 무엇인지, 어떻게 사용하는지 내가 직접 구현해보지도 않아서 그리고 막상 사용한 예들을 보니까 내 코드를 더 간결하게 만들 수 있을거란 생각이 들었다. 그래서 공부를 진행하였다.

Stream은 위에서도 말했듯, Java 8 버전 부터 추가된 기능이고, 컬렉션이나 배열 등의 저장요소를 하나씩 참조하여 함수형 인터페이스(람다식)를 적용하며 반복적으로 처리하게 해주는 기능이다.

처음에 남들과 같이 Stream이 InputStream, OutputStream같은 I/O Stream인줄 알았지만 그런 Stream은 아니다.

아래의 예를 보면 얼마나 가독성도 좋고 문법이 짧아지는지 알 수 있다.

Main.java

public class Main {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("apple", "banana", "orange", "strawberry");

        long count = 0;
        for(String fruit : fruits){
            if(fruit.contains("p")){
                count++;
            }
        }
        System.out.println(count);


        count = fruits.stream()
                      .filter(f -> f.contains("p"))
                      .count();
        
        System.out.println(count);

    }
}

기존의 방법은...
fruits 라는 컬렉션이 존재하고 그 컬렉션의 요소를 for문으로 돌면서 if문을 통해 fruit요소가 p를 가지고 있다면 count 개수를 한개 늘려라라고 수행을 하는 반면
아래의 스트림방식은 fruits를 순회하면서 그 인자 가 p를 포함하고 있으면 count메소드로 1씩 증가시켜준다.
이것으로 보아 불필요한(for, if) 문법을 걷어내고 직관적이기 때문에 가독성이 좋아진다!

Stream은 Array와 Collection에 자주 쓴다.
다른데서도 쓸 수 있겠지만, 저 두개보다는 빈도가 낮기때문에 두개를 자주 쓴다고 말을 했다.

자주쓰는 것들로 Stream을 생성하는 법은 아래와 같다.

//Collection의 Stream 생성
List<String> fruits = Arrays.asList("apple", "banana", "orange", "strawberry");
fruits.stream();

//Array의 Stream 생성
int[] array = {1, 2, 3, 4, 5};
Arrays.stream(array);

//Stream을 직접 만듦
Stream<String> str = Stream.of("a", "b");

Stream의 연산

Stream이 제공하는 다양한 연산을 이용하여 복잡한 작업들을 간단히 처리할 수 있다. Stream에 정의된 메소드 중에서 데이터 소스를 다루는 작업을 연산이라고 한다.
Stream이 제공하는 연산은 중간연산최종연산이 있다.
사용법은 객체.stream().중간연산().최종연산() 순서이다.

때문에 중간연산은 계속 이어서 여러개를 수행할 수 있지만 최종연산 뒤에는 중간연산을 붙일 수 없고 그 즉시 끝나게된다.

중간 연산의 특징

  • Stream을 return한다.
  • Stateless / Stateful 연산으로 더 상세하게 구분이 가능하다. ( 대부분은 Stateless지만 distinct나 sorted처럼 이전 소스 데이터를 참조해야 하는 연산은 Stateful 이다)
  • 대표적인 예) - filter, map, sorted, skip, limit, ....

최종 연산의 특징

  • Stream을 return 하지 않는다.
  • 대표적인 예) - count, allMatch, collect, forEach, min, max, ...

사용법대로 아까의 fruits를 해보면 다음과 같다.

fruits.stream() //stream생성
      .map(a -> a.toUpperCase(Locale.ROOT)) //인자 하나마다 대문자로 변경을해주고
      .forEach(System.out::println); // 각각을 console창에 출력해달라.

Stream을 잘 알아두면 기존의 for, if를 적게쓰고 가독성을 높일 수 있으니까 더 깊이 공부하자.

profile
💻 많이 짜보고 많이 경험해보자 https://lsj8367.tistory.com/ 블로그 주소 옮김

0개의 댓글