Java Stream API

lsj8367·2021년 4월 2일
0

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
기록을 많이 하자!💻

0개의 댓글