스터디 책 정리/모던 자바 인 액션

스트림

박상순 2023. 9. 11. 18:56

자바8 버전부터 API에 추가된 새로운 기능으로 데어터처리시 코드 구현이 아닌 선언형으로 컬렉션 데이터를 처리할 수 있다. parallelStream()을 사용한다면 멀티스레드 코드로 구현하지 않더라도 병렬처리가 가능하다.

기존의 자바 코드 8버전 미만

List<Dish> lowCaloricDishes = new ArrayList<>();
for (Dish dish : menu) {
    if (dish.getCalories() < 400) {
        lowCaloricDishes.add(dish);
    }
}

Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
    public int compoare(Dish dish1, Dish dish2) {
        return Integer.compare(dish1.getCalories(), dish2.getCalories());
    }
});

List<String> lowCaloricDishesName = new ArrayList<>();
for (Dish dish : lowCaloricDishes) {
    lowCaloricDishesName.add(dish.getName());
}


8버전 이상에서 stream 사용

List<String> lowCaloricDishesName =
    menu.stream()
        .filter(d -> d.getCalories() > 400)
        .sorted(comparing(Dish::getCalories))
        .map(Dish::getName)
        .collect(toList());
  • 가비지 변수를 만들 필요가 없음
  • 선언형으로 코드를 구현

 

stream 정의 : 데이터 처리 연산을 지원하도록 소스에서 추출된 연속된 요소

  • 연속된 요소: 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. 주로 계산식이 주를 이룬다. 이때 연속적은 순차적으로 접근함을 의미한다.
  • 소스: 스트림은 컬렉션, 배열, I/O 자원 등의 데이터 제공 소스로부터 데이터를 소비한다.
  • 데이터 처리 연산: 스트림은 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원하며, 순차적으로 또는 병렬로 실행할 수 있다.

스트림은 다음과 같은 두 가징 중요 특성이 있다.

  • 파이프라이닝: 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프라인을 구성할 수 있도록 스트림 자신을 반환한다. 그 덕에 게으름(lazyness), 쇼트서킷(short-circuiting) 같은 최적화도 얻을 수 있다.
  • 내부 반복: 반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.

컬렉션은 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조다. 즉, 컬렉션의 모든 요소는 컬렉션에 추가하기 전에 계산되어야 한다. 반면 스트림은 이론적으로 요청할 때만 요소를 계산하는 고정된 자료구조다. 이러한 스트림의 특성은 게으른 생성을 가능하게 한다. ==> 일종의 페이징 처리라고 생각하자

스트림은 반복자와 마찬가지로 한 번만 탐색할 수 있다. 탐색된 스트림의 요소는 소비된다. 재 탐색을 위해서는 초기 데이터 소스에 새로운 스트림을 생성해야한다.

 

외부 반복 - 기존의 java에서 처리하는 문법인 for-each, Iterator의 반복 저장 방식

내부 반복 - stream 라이브러리에서 반복을 처리 및 저장해주는 방식

내부 반복의 장점 : stream 라이브러리가 알아서 수행하므로 병렬성을 쉽게 얻을 수 있으며 stream 내부적으로 최적화 된 방법으로 데이터를 처리

 

스트림 연산

  • 스트림 연산을 연결하는 중간연산, 스트림을 닫는 최종연산으로 그룹지어져 있다.
  1. 중간 연산
    • 중간 연산은 마지막 연산을 실행하기 전까지 연산 되지 않고 중간연산들을 합쳐서 한번에 처리한다.
  2. 최종 연산
    • 스트림 파이프라인에서 결과를 반환하는 연산
List<Stirng> names = menu.stream() // 스트림 open
		.filter(dish -> dish.getCalories > 300) // 중간 연산 시작
		.map(Dish::getname)
		.limit(3) // 중간 연산 끝, short-circuit
		.collect(toList()); // 종단 연산
728x90

'스터디 책 정리 > 모던 자바 인 액션' 카테고리의 다른 글

병렬 데이터 처리와 성능  (0) 2023.09.12
스트림으로 데이터 수집  (0) 2023.09.12
스트림 활용  (0) 2023.09.11