SlideShare a Scribd company logo
람다, 스트림 API
참고
● 참고 도서
○ 자바 8 인 액션
● 예제 코드
○ https://github.com/clghks/javacafe_lambda_
stream
목차
● 람다
○ 람다란 무엇인가?
○ 함수형 인터페이스
○ 람다 활용 : 실행 어라운드 패턴
○ 메서드 레퍼런스
● 스트림 API
○ 스트림이란 무엇인가?
○ 스트림과 컬렉션
○ 스트림 연상
● 스트림 API 활용
○ 필터링과 슬라이싱
○ 매핑
○ 리듀싱
○ 스트림 만들기
● 병렬 데이터 처리와 성능
○ 순차 스트림을 병렬 스트림으로 변환하기
○ 스트림 성능 측정
○ 병렬 스트림의 올바른 사용법
람다(Lambda)
람다란 무엇인가?
● Java 7 ● 람다 사용
람다란 무엇인가?
● 람다 표현식
○ 메서드로 전달 할 수 있는 익명 함수를 단순화한 것
○ 이름은 없지만, 파라미터 리스트, 바디, 반환 형식, 예외 리스트를 가질 수 있다.
● 람다의 특징
○ 익명
■ 보통의 메서드와 달리 이름이 없으면 익명이라 표현한다.
○ 함수
■ 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다.
○ 전달
■ 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다.
○ 간결성
■ 익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없다.
람다란 무엇인가?
● 람다가 기술적으로 Java8 이전의 자바로 할 수 없었던 일을 해낸다던가 하는
드라마틱한 기술은 아니다.
● 람다 표현식을 이용하면 코드가 간결하고 유연해진다.
람다 표현식 문법
● 람다 표현식은 세부분으로 이루어진다.
○ 파라미터 리스트
■ Comparator의 compare 메서드의 파라미터
○ 화살표
■ 화살표(->)는 람다의 파라미터 리스트와 바디를 구분한다.
○ 람다의 바디
■ 두 사과의 무게를 비교한다.
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
람다 파라미터 람다 바디
화살표
람다 표현식 문법
● 식을 이용한 경우 (표현식)
(parameters) -> expression
● 문을 이용하는 경우 (구문)
○ 여러 문장을 포함할 수 있다.
(parameters) -> {
statements;
}
람다 표현식 문법
(String s) -> s.length()
(Apple a) -> a.getWeight() > 150
(int x, int y) -> {
System.out.println(“Result : ”);
System.out.println(x + y);
}
() -> 42
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
람다 표현식 문법 (사용 예제)
사용 사례 람다 예제
불린 표현식 (List<String> list) -> list.isEmpty()
객체 생성 () -> new Apple(10)
객체에서 소비 (Apple a) -> {
System.out.println(a.getWeight());
}
두 값을 조합 (int a, int b) -> a * b
퀴즈 - 람다 표현식 문법
● 람다 규칙에 맞지 않는 람다 표현식을 고르시오.
1. () -> {}
2. () -> “Raoul”
3. () -> {return “Mario”;}
4. (Integer i) -> return “Alan” + i
5. (String s) -> {“Iron Man”;}
퀴즈 정답
● 4번과 5번이 유효하지 않은 람다 표현식
4. (Integer i) -> {return “Alan” + i;} 처럼 되어야 올바른 람다 표현식이다.
5. (String s) -> “Iron Man” 또는 (String s) -> {return “Iron Man”;} 처럼 되어야
올바른 람다 식이다.
함수형 인터페이스
● 람다 표현식은 함수형 인터페이스라는 문맥에서 사용할 수 있다.
● 함수형 인터페이스는 정확히 하나의 추상 메서드를 지정하는 인터페이스다.
● 자바 API의 함수형 인터페이스로 Comparator, Runnable 등이 있다.
● 디폴트 메서드가 있더라도 추상 메서드가 오직 하나면 함수형 인터페이스다.
함수형 인터페이스
코드!!!
함수형 인터페이스
● 람다 표현식을 사용하지 않고 함수형 인터페이스 사용 해보기
함수형 인터페이스
● 람다 표현식으로 함수형 인터페이스 사용 해보기
함수형 인터페이스 사용
● java.util.function 패키지로 여러가지 함수형 인터페이스를 제공한다.
○ Predicate, Consumer, Function 등
함수형 인터페이스 사용 - Predicate
● test 라는 추상 메서드를 정의
● T 객체를 파라미터로 받아 Boolean을 반환 한다.
함수형 인터페이스 사용 - Consumer
● accept 라는 추상 메서드를 정의
● T 객체를 파라미터로 받아 void를 반환한다.
함수형 인터페이스 사용 - Function
● apply 라는 추상 메서드를 정의
● T를 파라미터로 받아 R 객체를 반환한다.
기본형 특화 함수 인터페이스
● 자바의 모든 형식은 참조형(byte, Integer, Object, List 등) 아니면 기본형 (int,
double, byte, char) 이다.
● 기본형을 참조형으로 변환 동작을 박싱(boxing)이라고 한다.
● 참조형을 기본형으로 변환 동작을 언박싱(unboxing)이라고 한다.
● 박싱과 언박싱이 자동으로 이루어지는 오토박싱(autoboxing)이라고 한다.
● 박싱, 언박싱, 오토박싱 과정은 비용이 소모 된다.
● 오토박싱에 의한 비용을 줄이기 위해 기본형 특화 함수형 인터페이스를
제공한다.
기본형 특화 함수 인터페이스
● 기본형 특화 함수 인터페이스 사용
기본형 특화 함수 인터페이스
● 자바8 대표적인 함수 인터페이스
함수형 인터페이스 기본형 특화 함수형 인터페이스
Predicate<T> IntPredicate, LongPredicate, DoublePredicate
Consumer<T> IntConsumer, LongConsumer, DoubleConsumer
Function<T, R> IntFunction<R>, IntToDoubleFunction, IntToLongFunction,
LongFunction<R>, LongToDoubleFunction, LongToIntFunction,
DoubleFunction<R>, ToIntFunction<T>, ToDoubleFunction<T>,
ToLongFunction<T>
람다 캡처링
● 람다 표현식에서 파라미터로 넘겨진 변수가 아닌 외부에 정의된 변수를 활용할
수 있다.
○ 지역 변수는 final 로 선언되거나 final 처럼 취급 되어야한다.
람다 활용 : 실행 어라운드 패턴
● 자원 처리에 사용하는 순환패턴은 자원을 열고, 처리한 다음에, 자원을 닫는
순서로 이루어진다.
● 설정(setup)과 정리(cleanup) 과정은 대부분 비슷하다.
● 실제 자원을 처리하는 코드를 설정과 정리 두 과정에 둘러싸는 형태를 갖는다.
초기화/준비 코드
(setup)
작업 A
정리/마무리 코드
(cleanup)
초기화/준비 코드
(setup)
작업 B
정리/마무리 코드
(cleanup)
람다 활용 : 실행 어라운드 패턴
● 파일에서 한 행을 읽는 코드
- 한번에 두줄을 읽는 요구 사항 추가!!!
람다 활용 : 실행 어라운드 패턴
● 함수형 인터페이스를 이용하여 동작 전달
- 함수형 인터페이스 추가
- 동작을 파라미터로 전달
람다 활용 : 실행 어라운드 패턴
● 한번에 두줄 읽는 기능 추가
메서드 레퍼런스
메서드 레퍼런스
● 메서드 레퍼런스는 람다 표현식을 축약한 것
● 람다 표현식보다 메서드 레퍼런스를 사용하는 것이 가독성이 좋다.
● 메서드명 앞에 구분자(::)를 붙이는 방식으로 메서드 레퍼런스를 활용 할 수
있다.
● 실제 메서드를 호출하는 것이 아니므로 괄호는 필요 없음
람다 표현식 메서드 레퍼런스
(Apple a) -> a.getWeight() Apple::getWeight
() -> Thread.currentThread().dumpstack() Thread.currentThread()::dumpStack
(str, i) -> str.substring(i) String::substring
(String s) -> System.out.println(s) System.out::println
Predicate 조합
● Predicate 인터페이스는 negate, and, or 메서드를 제공한다.
Function 조합
● Function 인터페이스는 andThen, compose 두 가지 디폴트 메서드를
제공한다.
요약
● 람다 표현식은 익명 함수의 일종이다.
● 람다 표현식으로 간결한 코드를 구현할 수 있다.
● 함수형 인터페이스는 하나의 추상 메서드만을 정의하는 인터페이스다.
● 함수형 인터페이스를 기대하는 곳에서만 람다 표현식을 사용할 수 있다.
● java.util.function 패키지는 Predicate<T>, Function<T, R>, Consumer<T> 등을
포함해서 자주 사용하는 다양한 함수형 인터페이스를 제공한다.
● 박싱 동작을 피할 수 있도록 IntPredicate, IntToLongFunction 등과 같은 기본형
특화 인터페이스를 제공한다.
● 실행 어라운드 패턴을 람다와 활용하면 유연성과 재사용성을 추가로 얻을 수
있다.
● 메서드 레퍼런스를 이용하면 기존의 메서드 구현을 재사용하고 직접 전달할 수
있다.
스트림 API
스트림이란 무엇인가?
● Java 7 ● 스트림 사용
스트림이란 무엇인가?
● 데이터 컬렉션 반복을 멋지게 처리할 수 있다.
● 컬렉션을 SQL Query 처럼 처리 할 수 있다.
○ ex) 400칼로리 이상의 요리를 찾기
■ SELECT name FROM dishes WHERE calorie > 400
■ dishes.stream().filter(d -> d.getCalories() < 400).map(Dish::getName).collect(toList())
● 멀티 스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수
있다.
스트림이란 무엇인가?
● 선언형
○ 루프와 if 조건문 등의 제어 블록을 사용하여 어떻게 동작 해야하는지 지정할 필요가 없다.
○ 간결하고 가독성이 좋아진다.
● 조립할 수 있음
○ filter, sorted, map, collect 같은 연산을 연결하여 처리를 할 수 있다.
○ 유연성이 좋아진다.
● 병렬화
○ 성능이 좋아진다.
스트림 시작하기
● filter
○ 람다를 인수로 받아 스트림에서 특정 요소를 제외 시킨다.
● map
○ 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출한다.
● limit
○ 정해진 개수 이상의 요소가 스트림에 저장되지 못하게 스트림 크기를 축소한다.
● sorted
○ 람다를 이용하여 스트림 요소를 정렬한다.
● distinct
○ 스트림에 저장되어 있는 중복 요소를 제거 한다.
스트림 시작하기
● collect
○ 스트림을 다른 형식으로 변환한다.
● forEach
○ 스트림의 각 요소를 소비하면서 람다를 적용한다.
● count
○ 스트림의 요소의 개수를 반환한다.
스트림 시작하기
● 스트림에서 메뉴를 필터링해서 세 개의 고칼로리 요리명 찾기
스트림과 컬렉션
● 컬렉션
○ 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조
● 스트림
○ 요청할 때만 요소를 계산하는 고정된 자료구조
스트림과 컬렉션 - 딱 한번만 탐색할 수 있다
● 한번 탐색한 요소를 다시 탐색하려면 초기 데이터 소스에서 새로운 스트림을
만들어야 한다.
스트림과 컬렉션 - 외부 반복과 내부 반복
● 외부 반복
○ 컬렉션 인터페이스를 사용하려면 사용자가 직접 요소를 반복 해야한다.
● 내부 반복
○ 함수에 어떤 작업을 수행할지만 지정하면 모든 것이 알아서 처리된다.
스트림 연산
● 스트림 인터페이스의 연산을 크게 중간 연산과 최종 연산으로 구분 할 수 있다.
스트림 연산
● 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한번에 처리 한다.
중간 연산
● 최종 연산을 수행하기 전까지는 아무 연산도 수행하지 않는다.
● 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종
연산으로 한 번에 처리 한다.
최종 연산
● 스트림 파이프라인에서 결과를 도출 한다.
● 최종 연산에 의해 List, Integer void 등 스트림 이외의 결과가 반환된다.
퀴즈 - 중간 연산과 최종 연산
● 다음 스트림 파이프라인에서 중간 연산과 최종 연산을 구별하시오.
long count = menu.stream()
.filter( d -> d.getCalories() > 300)
.distinct()
.limit(3)
.count();
퀴즈 정답
● 중간 연산
○ Filter, distinct, limit
● 최종 연산
○ count
요약
● 스트림은 소스에서 추출된 연속된 요소로, 데이터 처리 연산을 지원한다.
● 스트림은 내부 반복을 지원한다.
● 스트림에는 중간 연산과 최종 연산이 있다.
● 중간 연산을 이용해서 파이프라인을 구성할 수 있지만 중간 연산으로는 어떤
결과도 생성할 수 없다.
● 스트림의 요소는 요청할 때만 계산된다.
스트림 API 활용
필터링과 슬라이싱
● 프레디케이트로 필터링
○ 프레디케이트와 일치하는 모든 요소를 포함하는 스트림을 반환한다.
필터링과 슬라이싱
● 고유 요소 필터링
○ 고유 요소로 이루어진 스트림을 반환하는 distinct라는 메서드를 지원한다. (중복제거)
필터링과 슬라이싱
● 스트림 축소
○ 주어진 사이즈 이하의 크기를 갖는 새로운 스트림을 반환한다.
○ limit(n) 을 호출하면 처음 n개 요소를 선택한 다음 즉시 결과를 반환한다.
필터링과 슬라이싱
● 요소 건너뛰기
○ 처음 n개 요소를 제외한 스트림을 반환하는 skip(n) 메서드를 지원한다.
○ n개 이하의 요소를 포함하는 스트림에 skip(n)을 호출하면 빈 스트림이 반환된다.
퀴즈
● 스트림을 이용해서 처음 등장하는 두 고기 요리를 필터링하시오.
퀴즈
● 스트림을 이용해서 처음 등장하는 두 고기 요리를 필터링하시오.
● 정답 :
List<Dish> dishes = menu.stream()
.filter(d -> d.geType() == Dish.Type.MEAT)
.limit(2)
.collect(toList());
매핑
● 스트림의 각 요소에 함수 적용하기
○ 스트림은 함수를 인수로 받는 map 메서드를 지원한다.
○ 인수로 받은 함수를 적용한 결과가 새로운 요소로 매핑된다.
● ex) Dish::getName을 map 메서드로 전달해서 요리명을 추출하는 코드
● ex) 다른 map 메서드를 연결할 수 있다.
매핑
● 스트림 평면화
○ flatMap은 각 배열을 스트림이 아니라 스트림의 콘텐츠로 매핑한다.
● ex) [“Hello”, “World”] 리스트를 [“H”, “e”, “l”, “O”, “W”, “r”, “d”] 로 변환해보자
매핑
매핑
● flatMap 사용하기
매핑
map과 Arrays.stream 활용
● 배열 스트림 대신 문자열 스트림이 필요할 경우
Arrays.stream을 사용할 수 있다.
검색과 매칭
● anyMatch
○ 적어도 한 요소와 일치하는지 확일 할때 사용
● allMatch
○ 모든 요소가 주어진 프레디케이드와 일치하는지 검사
● noneMatch
○ 주어진 프레디케이와 일치하는 요소가 없는지 확인한다.
anyMach, allMatch, noneMatch는 스트림의 쇼트서킷 기법
검색과 매칭
쇼트서킷
● 모든 스트림을 처리하지 않고 결과를 반환 할 수 있다.
● 무한한 요소를 가진 스트림을 유한한 크기로 줄일 수 있는 유용한 연산
○ ex) anyMatch 에서 하나라도 일치하는 결과가 나오면 나머지
결과에 상관없이 True를 반환한다.
검색과 매칭
● findAny
○ 현재 스트림에서 임의 요소를 반환한다.
● findFirst
○ 현재 스트림에서 첫 번째 요소를 찾아 반환한다. (병렬 실행시 성능 이슈)
● findFirst와 findAny는 병렬성 때문에 사용 된다.
○ 병렬 실행에서는 첫 번째 요소를 찾기 어렵다.
반환 순서가 상관 없다면 병렬 스트림에서는 findAny를 사용하자.
검색과 매칭
Optional
● 값이 존재하는지 확인하고 값이 없을 때 어떻게 처리할 것인지 강제하는 기능
을 제공한다
○ isPresent 는 Optional이 값을 포함하면 True를 반환하고,
값을 포함하지 않으면 false를 반환한다.
○ ifPresent 는 값이 있으면 주어진 블록을 실행한다.
○ get 은 값이 존재하면 반환하고, 값이 없으면 NoSuchElementException을 일으킨다.
○ orElse 는 값이 있으면 값을 반환하고, 값이 없으면 기본값을 반환한다.
리듀싱
● 모든 스트림 요소를 처리해서 값으로 도출하는 연산
○ 메뉴의 모든 칼로리 합계를 구하기
○ 메뉴의 가장 작은 칼로리 찾기
○ 메뉴의 가장 높은 칼로리 찾기
● 초기 값을 지정하지 않으면 Optional 객체 반환한다.
● 내부 반복이 추상화되면서 병렬로 reduce를 실핼 할 수 있다.
리듀싱
리듀싱
숫자형 스트림
● 기본형 특화 스트림
○ 스트림 API는 박싱비용을 피할 수 있도록 IntStream, DoubleStream, LongStream을 제공한다.
● 숫자 범위
○ IntStream과 LongStream은 range와 rangeClose 메서드를 제공한다.
■ range 메서드는 시작값과 종료값이 결과에 포함되지 않는다.
■ rangeClose 메서드는 시작값과 종료값이 결과에 포함된다.
스트림 만들기
● 값으로 스트림 만들기
○ 임의의 수를 인수로 받는 정적 메서드 Stream.of를 이용해서 스트림을 만들 수 있다.
○ Stream.empty를 이용해서 스트림을 비울 수 있다.
● 배열로 스트림 만들기
○ Arrays.stream을 이용해서 스트림을 만들 수 있다.
● 파일로 스트림 만들기
○ java.nio.file.Files를 이용해서 스트림을 만들 수 있다.
● 함수로 무한 스트림 만들기
○ Stream.iterate와 Stream.generate를 이용해서 무한 스트림을 만들 수 있다.
■ Stream.iterate는 기존의 결과에 의존해서 순차적으로 연산을 수행
■ Stream.generate는 새로운 값을 생산한다.
● IntStream을 이용하면 박싱 연산 문제를 해결 할 수 있다.
스트림 만들기
병렬 데이터 처리와 성능
병렬 스트림
● 컬렉션에 parallelStream을 호출 하면 병렬 스트림이 생성된다.
● 병렬 스트림을 이용하면 모든 멀티코어 프로세서가 각가의 청크를 처리하도록
할당할 수 있다.
병렬 스트림
● 숫자 n을 인수로 받아서 1부터 n까지 모든 숫자의 합계를 구하는 코드
병렬 스트림
● 숫자 n이 커진다면 연산을 병렬로 처리하는 것이 좋을까?
● 병렬로 처리하기 위해서 어디를 수정 해야할까?
● 결과 변수는 어떻게 동기화 해야할까?
● 몇 개의 스레드를 사용해야할까?
● 숫자는 어떻게 생성할까?
● 생성된 숫자는 누가 더할까?
순차 스트림을 병렬 스트림으로 변환하기
● 순차 스트림에 parallel 메서드를 호출 하면 기존의 함수형 리듀싱 연산이
병렬로 처리된다.
병렬 스트림
->
순차 스트림을 병렬 스트림으로 변환하기
스트림 성능 측정
● 병렬화를 이용하면 순차나 반복 형식에 비해 성능이 더 좋아질 것이라
추측했다.
● 병렬화를 이용하면 성능이 더 좋아지는 비교해보자.
스트림 성능 측정
● 순차 스트림 ● For 루프를 사용
스트림 성능 측정
● 병렬 스트림
스트림 성능 측정
● 병렬 스트림이 순차 스트림보다 성능이 나쁘게 나왔다.
○ iterate가 박싱된 객체를 생성하므로 이를 다시 언박싱하는 과정이 필요했다.
○ iterate는 병렬로 실행될 수 있도록 독립적인 청크로 분할하기가 어렵다.
● 리듀싱 과정을 시작하는 시점에 전제 숫자 리스트가 준비 되지 않았음으로
스트림을 병렬로 처리할 수 있도록 청크로 분활할 수 없다.
● 스트림이 병렬로 처리되도록 지시 했지만 순차처리 방식과 크게 다른 점이
없으므로 스레드를 할당하는 오버헤드만 증가 했다.
더 특화된 메서드 사용
● 멀티코어 프로세서를 활용해서 효과적으로 합계 연산을 병렬로 실행하려면
어떻게 해야할까?
● LongStream.rangeClosed 메서드는 iterate에 비해 다음과 같은 장점을
제공한다.
○ LongStream.rangeClosed는 기본형 long을 직접 사용하므로 박싱과 언박싱 오버헤드가
사라진다.
○ LongStream.rangeClosed는 쉽게 청크로 분할할 수 있는 숫자 범위를 생산한다.
■ 1-20 범위로 숫자를 각각 1-5, 6-10, 11-15, 16-20 범위의 숫자로 분할 할 수 있다.
더 특화된 메서드 사용
● LongStream.rangeClosed 적용
더 특화된 메서드 사용
● 순차 스트림 ● 병렬 스트림
더 특화된 메서드 사용
● 순차 실행보다 빠른 성능을 갖는 병렬 리듀싱을 만들었다.
● 이번에는 실질적으로 리듀싱 연상이 병렬로 실행된다.
● 올바른 자료구조를 선택해야 병렬 실행도 최적의 성능을 발휘할 수 있다.
● 병렬화는 완전 공짜가 아니다.
● 코어 간에 데이터 전송 시간보다 훨씬 오래 걸리는 작업만 병렬로 다른
코어에서 수행하는 것이 바람직하다.
● 병렬화해서 코드 실행 속도를 빠르게 하고싶면 항상 병렬화를 올바르게
사용하고 있는지 확인해야 한다.
병렬 스트림의 올바른 사용법
● 숫자 n까지의 자연수를 더하면서 공유된 누적자를 바꾸는 코드
병렬 스트림의 올바른 사용법
● total을 접근 할 때마다 데이터 레이스 문제가 발생
● 여러 스레드에서 공유하는 객체의 상태를 바꾸는 forEach 블록 내부에서 add
메서드를 호출하면서 문제 발생
병렬 스트림 효과적으로 사용하기
● 확신이 서지 않는다면 직접 측정하라.
● 박싱을 주의하라
● 순차 스트림보다 병렬 스트림에서 성능이 떨어지는 연산이 있다.
● 스트림에서 수행하는 전체 파이프라인 연산 비용을 고려하라.
● 소량의 데이터에서는 병렬 스트림 도움 되지 않는다.
● 스트림을 구성하는 자료구조가 적절한지 확인하라.
● 스트림의 특성과 파이프라인의 중간 연상이 스트림의 특성을 어떻게
바꾸는지에 따라 분해 과정의 성능이 달라질 수 있다.
● 최종 연산의 병합 과정 비용을 살펴보라.

More Related Content

PDF
Haskell study 9
PPTX
PDF
Haskell study 15
PDF
Haskell study 14
PDF
Haskell study 10
PPTX
Howto_Tensorflow+Linear Regression
PDF
Haskell study 12
PDF
Template at c++
Haskell study 9
Haskell study 15
Haskell study 14
Haskell study 10
Howto_Tensorflow+Linear Regression
Haskell study 12
Template at c++

What's hot (19)

PDF
2012 Ds 01
PDF
Haskell study 4
PDF
Haskell study 13
PDF
5 swift 기초함수
PDF
나에 첫번째 자바8 람다식 지앤선
PPTX
Java8 람다
PDF
자바8 람다 나머지 공개
PDF
Haskell study 5
PDF
동시성 프로그래밍 하기 좋은 Clojure
PPTX
Java standard(8~13)
PDF
Start IoT with JavaScript - 5.객체2
PDF
Haskell study 6
PPT
강의자료3
PDF
6 swift 고급함수
PDF
[Swift] Protocol (1/2)
PDF
Java stream v0.1
PDF
Haskell study 8
PDF
Python basic
PDF
C++’s move semantics
2012 Ds 01
Haskell study 4
Haskell study 13
5 swift 기초함수
나에 첫번째 자바8 람다식 지앤선
Java8 람다
자바8 람다 나머지 공개
Haskell study 5
동시성 프로그래밍 하기 좋은 Clojure
Java standard(8~13)
Start IoT with JavaScript - 5.객체2
Haskell study 6
강의자료3
6 swift 고급함수
[Swift] Protocol (1/2)
Java stream v0.1
Haskell study 8
Python basic
C++’s move semantics
Ad

Similar to 람다, 스트림 Api (20)

PDF
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 씹고 뜯고 맛보고 즐기는 스트림 API(박용권)
PDF
자바8강의 2강. Stream API
PDF
씹고 뜯고 맛보고 즐기는 스트림 API
PPTX
3. stream api
PPTX
자바 8 학습
PPTX
스트림Api 스터디 2일
PPTX
자바 8
PDF
Java8 & Lambda
PDF
Java stream v0.1
PDF
자바8 스트림 API 소개
PPTX
1. introduction to java8
PDF
SpringCamp 2013 : About Jdk8
PDF
Java jungsuk3 ch14_lambda_stream
PDF
자바8강의 0강. java8 overview
PDF
3주차. stream api advance
PPTX
(망작)이것이 자바다 Chap.16 스트림&병렬처리 Stream&parallel processing(java)
PPTX
동작 파라미터와 람다 In java 8
PDF
JDK 변천사
PDF
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
PDF
자바8강의 1강. lambda expression
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 씹고 뜯고 맛보고 즐기는 스트림 API(박용권)
자바8강의 2강. Stream API
씹고 뜯고 맛보고 즐기는 스트림 API
3. stream api
자바 8 학습
스트림Api 스터디 2일
자바 8
Java8 & Lambda
Java stream v0.1
자바8 스트림 API 소개
1. introduction to java8
SpringCamp 2013 : About Jdk8
Java jungsuk3 ch14_lambda_stream
자바8강의 0강. java8 overview
3주차. stream api advance
(망작)이것이 자바다 Chap.16 스트림&병렬처리 Stream&parallel processing(java)
동작 파라미터와 람다 In java 8
JDK 변천사
2014.07.26 KSUG와 지앤선이 함께하는 테크니컬 세미나 - 나의 첫번째 자바8 람다식 (정대원)
자바8강의 1강. lambda expression
Ad

람다, 스트림 Api

  • 2. 참고 ● 참고 도서 ○ 자바 8 인 액션 ● 예제 코드 ○ https://github.com/clghks/javacafe_lambda_ stream
  • 3. 목차 ● 람다 ○ 람다란 무엇인가? ○ 함수형 인터페이스 ○ 람다 활용 : 실행 어라운드 패턴 ○ 메서드 레퍼런스 ● 스트림 API ○ 스트림이란 무엇인가? ○ 스트림과 컬렉션 ○ 스트림 연상 ● 스트림 API 활용 ○ 필터링과 슬라이싱 ○ 매핑 ○ 리듀싱 ○ 스트림 만들기 ● 병렬 데이터 처리와 성능 ○ 순차 스트림을 병렬 스트림으로 변환하기 ○ 스트림 성능 측정 ○ 병렬 스트림의 올바른 사용법
  • 5. 람다란 무엇인가? ● Java 7 ● 람다 사용
  • 6. 람다란 무엇인가? ● 람다 표현식 ○ 메서드로 전달 할 수 있는 익명 함수를 단순화한 것 ○ 이름은 없지만, 파라미터 리스트, 바디, 반환 형식, 예외 리스트를 가질 수 있다. ● 람다의 특징 ○ 익명 ■ 보통의 메서드와 달리 이름이 없으면 익명이라 표현한다. ○ 함수 ■ 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다. ○ 전달 ■ 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다. ○ 간결성 ■ 익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없다.
  • 7. 람다란 무엇인가? ● 람다가 기술적으로 Java8 이전의 자바로 할 수 없었던 일을 해낸다던가 하는 드라마틱한 기술은 아니다. ● 람다 표현식을 이용하면 코드가 간결하고 유연해진다.
  • 8. 람다 표현식 문법 ● 람다 표현식은 세부분으로 이루어진다. ○ 파라미터 리스트 ■ Comparator의 compare 메서드의 파라미터 ○ 화살표 ■ 화살표(->)는 람다의 파라미터 리스트와 바디를 구분한다. ○ 람다의 바디 ■ 두 사과의 무게를 비교한다. (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()); 람다 파라미터 람다 바디 화살표
  • 9. 람다 표현식 문법 ● 식을 이용한 경우 (표현식) (parameters) -> expression ● 문을 이용하는 경우 (구문) ○ 여러 문장을 포함할 수 있다. (parameters) -> { statements; }
  • 10. 람다 표현식 문법 (String s) -> s.length() (Apple a) -> a.getWeight() > 150 (int x, int y) -> { System.out.println(“Result : ”); System.out.println(x + y); } () -> 42 (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())
  • 11. 람다 표현식 문법 (사용 예제) 사용 사례 람다 예제 불린 표현식 (List<String> list) -> list.isEmpty() 객체 생성 () -> new Apple(10) 객체에서 소비 (Apple a) -> { System.out.println(a.getWeight()); } 두 값을 조합 (int a, int b) -> a * b
  • 12. 퀴즈 - 람다 표현식 문법 ● 람다 규칙에 맞지 않는 람다 표현식을 고르시오. 1. () -> {} 2. () -> “Raoul” 3. () -> {return “Mario”;} 4. (Integer i) -> return “Alan” + i 5. (String s) -> {“Iron Man”;}
  • 13. 퀴즈 정답 ● 4번과 5번이 유효하지 않은 람다 표현식 4. (Integer i) -> {return “Alan” + i;} 처럼 되어야 올바른 람다 표현식이다. 5. (String s) -> “Iron Man” 또는 (String s) -> {return “Iron Man”;} 처럼 되어야 올바른 람다 식이다.
  • 14. 함수형 인터페이스 ● 람다 표현식은 함수형 인터페이스라는 문맥에서 사용할 수 있다. ● 함수형 인터페이스는 정확히 하나의 추상 메서드를 지정하는 인터페이스다. ● 자바 API의 함수형 인터페이스로 Comparator, Runnable 등이 있다. ● 디폴트 메서드가 있더라도 추상 메서드가 오직 하나면 함수형 인터페이스다.
  • 16. 함수형 인터페이스 ● 람다 표현식을 사용하지 않고 함수형 인터페이스 사용 해보기
  • 17. 함수형 인터페이스 ● 람다 표현식으로 함수형 인터페이스 사용 해보기
  • 18. 함수형 인터페이스 사용 ● java.util.function 패키지로 여러가지 함수형 인터페이스를 제공한다. ○ Predicate, Consumer, Function 등
  • 19. 함수형 인터페이스 사용 - Predicate ● test 라는 추상 메서드를 정의 ● T 객체를 파라미터로 받아 Boolean을 반환 한다.
  • 20. 함수형 인터페이스 사용 - Consumer ● accept 라는 추상 메서드를 정의 ● T 객체를 파라미터로 받아 void를 반환한다.
  • 21. 함수형 인터페이스 사용 - Function ● apply 라는 추상 메서드를 정의 ● T를 파라미터로 받아 R 객체를 반환한다.
  • 22. 기본형 특화 함수 인터페이스 ● 자바의 모든 형식은 참조형(byte, Integer, Object, List 등) 아니면 기본형 (int, double, byte, char) 이다. ● 기본형을 참조형으로 변환 동작을 박싱(boxing)이라고 한다. ● 참조형을 기본형으로 변환 동작을 언박싱(unboxing)이라고 한다. ● 박싱과 언박싱이 자동으로 이루어지는 오토박싱(autoboxing)이라고 한다. ● 박싱, 언박싱, 오토박싱 과정은 비용이 소모 된다. ● 오토박싱에 의한 비용을 줄이기 위해 기본형 특화 함수형 인터페이스를 제공한다.
  • 23. 기본형 특화 함수 인터페이스 ● 기본형 특화 함수 인터페이스 사용
  • 24. 기본형 특화 함수 인터페이스 ● 자바8 대표적인 함수 인터페이스 함수형 인터페이스 기본형 특화 함수형 인터페이스 Predicate<T> IntPredicate, LongPredicate, DoublePredicate Consumer<T> IntConsumer, LongConsumer, DoubleConsumer Function<T, R> IntFunction<R>, IntToDoubleFunction, IntToLongFunction, LongFunction<R>, LongToDoubleFunction, LongToIntFunction, DoubleFunction<R>, ToIntFunction<T>, ToDoubleFunction<T>, ToLongFunction<T>
  • 25. 람다 캡처링 ● 람다 표현식에서 파라미터로 넘겨진 변수가 아닌 외부에 정의된 변수를 활용할 수 있다. ○ 지역 변수는 final 로 선언되거나 final 처럼 취급 되어야한다.
  • 26. 람다 활용 : 실행 어라운드 패턴 ● 자원 처리에 사용하는 순환패턴은 자원을 열고, 처리한 다음에, 자원을 닫는 순서로 이루어진다. ● 설정(setup)과 정리(cleanup) 과정은 대부분 비슷하다. ● 실제 자원을 처리하는 코드를 설정과 정리 두 과정에 둘러싸는 형태를 갖는다. 초기화/준비 코드 (setup) 작업 A 정리/마무리 코드 (cleanup) 초기화/준비 코드 (setup) 작업 B 정리/마무리 코드 (cleanup)
  • 27. 람다 활용 : 실행 어라운드 패턴 ● 파일에서 한 행을 읽는 코드 - 한번에 두줄을 읽는 요구 사항 추가!!!
  • 28. 람다 활용 : 실행 어라운드 패턴 ● 함수형 인터페이스를 이용하여 동작 전달 - 함수형 인터페이스 추가 - 동작을 파라미터로 전달
  • 29. 람다 활용 : 실행 어라운드 패턴 ● 한번에 두줄 읽는 기능 추가
  • 31. 메서드 레퍼런스 ● 메서드 레퍼런스는 람다 표현식을 축약한 것 ● 람다 표현식보다 메서드 레퍼런스를 사용하는 것이 가독성이 좋다. ● 메서드명 앞에 구분자(::)를 붙이는 방식으로 메서드 레퍼런스를 활용 할 수 있다. ● 실제 메서드를 호출하는 것이 아니므로 괄호는 필요 없음 람다 표현식 메서드 레퍼런스 (Apple a) -> a.getWeight() Apple::getWeight () -> Thread.currentThread().dumpstack() Thread.currentThread()::dumpStack (str, i) -> str.substring(i) String::substring (String s) -> System.out.println(s) System.out::println
  • 32. Predicate 조합 ● Predicate 인터페이스는 negate, and, or 메서드를 제공한다.
  • 33. Function 조합 ● Function 인터페이스는 andThen, compose 두 가지 디폴트 메서드를 제공한다.
  • 34. 요약 ● 람다 표현식은 익명 함수의 일종이다. ● 람다 표현식으로 간결한 코드를 구현할 수 있다. ● 함수형 인터페이스는 하나의 추상 메서드만을 정의하는 인터페이스다. ● 함수형 인터페이스를 기대하는 곳에서만 람다 표현식을 사용할 수 있다. ● java.util.function 패키지는 Predicate<T>, Function<T, R>, Consumer<T> 등을 포함해서 자주 사용하는 다양한 함수형 인터페이스를 제공한다. ● 박싱 동작을 피할 수 있도록 IntPredicate, IntToLongFunction 등과 같은 기본형 특화 인터페이스를 제공한다. ● 실행 어라운드 패턴을 람다와 활용하면 유연성과 재사용성을 추가로 얻을 수 있다. ● 메서드 레퍼런스를 이용하면 기존의 메서드 구현을 재사용하고 직접 전달할 수 있다.
  • 36. 스트림이란 무엇인가? ● Java 7 ● 스트림 사용
  • 37. 스트림이란 무엇인가? ● 데이터 컬렉션 반복을 멋지게 처리할 수 있다. ● 컬렉션을 SQL Query 처럼 처리 할 수 있다. ○ ex) 400칼로리 이상의 요리를 찾기 ■ SELECT name FROM dishes WHERE calorie > 400 ■ dishes.stream().filter(d -> d.getCalories() < 400).map(Dish::getName).collect(toList()) ● 멀티 스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.
  • 38. 스트림이란 무엇인가? ● 선언형 ○ 루프와 if 조건문 등의 제어 블록을 사용하여 어떻게 동작 해야하는지 지정할 필요가 없다. ○ 간결하고 가독성이 좋아진다. ● 조립할 수 있음 ○ filter, sorted, map, collect 같은 연산을 연결하여 처리를 할 수 있다. ○ 유연성이 좋아진다. ● 병렬화 ○ 성능이 좋아진다.
  • 39. 스트림 시작하기 ● filter ○ 람다를 인수로 받아 스트림에서 특정 요소를 제외 시킨다. ● map ○ 람다를 이용해서 한 요소를 다른 요소로 변환하거나 정보를 추출한다. ● limit ○ 정해진 개수 이상의 요소가 스트림에 저장되지 못하게 스트림 크기를 축소한다. ● sorted ○ 람다를 이용하여 스트림 요소를 정렬한다. ● distinct ○ 스트림에 저장되어 있는 중복 요소를 제거 한다.
  • 40. 스트림 시작하기 ● collect ○ 스트림을 다른 형식으로 변환한다. ● forEach ○ 스트림의 각 요소를 소비하면서 람다를 적용한다. ● count ○ 스트림의 요소의 개수를 반환한다.
  • 41. 스트림 시작하기 ● 스트림에서 메뉴를 필터링해서 세 개의 고칼로리 요리명 찾기
  • 42. 스트림과 컬렉션 ● 컬렉션 ○ 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료구조 ● 스트림 ○ 요청할 때만 요소를 계산하는 고정된 자료구조
  • 43. 스트림과 컬렉션 - 딱 한번만 탐색할 수 있다 ● 한번 탐색한 요소를 다시 탐색하려면 초기 데이터 소스에서 새로운 스트림을 만들어야 한다.
  • 44. 스트림과 컬렉션 - 외부 반복과 내부 반복 ● 외부 반복 ○ 컬렉션 인터페이스를 사용하려면 사용자가 직접 요소를 반복 해야한다. ● 내부 반복 ○ 함수에 어떤 작업을 수행할지만 지정하면 모든 것이 알아서 처리된다.
  • 45. 스트림 연산 ● 스트림 인터페이스의 연산을 크게 중간 연산과 최종 연산으로 구분 할 수 있다.
  • 46. 스트림 연산 ● 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한번에 처리 한다.
  • 47. 중간 연산 ● 최종 연산을 수행하기 전까지는 아무 연산도 수행하지 않는다. ● 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한 번에 처리 한다.
  • 48. 최종 연산 ● 스트림 파이프라인에서 결과를 도출 한다. ● 최종 연산에 의해 List, Integer void 등 스트림 이외의 결과가 반환된다.
  • 49. 퀴즈 - 중간 연산과 최종 연산 ● 다음 스트림 파이프라인에서 중간 연산과 최종 연산을 구별하시오. long count = menu.stream() .filter( d -> d.getCalories() > 300) .distinct() .limit(3) .count();
  • 50. 퀴즈 정답 ● 중간 연산 ○ Filter, distinct, limit ● 최종 연산 ○ count
  • 51. 요약 ● 스트림은 소스에서 추출된 연속된 요소로, 데이터 처리 연산을 지원한다. ● 스트림은 내부 반복을 지원한다. ● 스트림에는 중간 연산과 최종 연산이 있다. ● 중간 연산을 이용해서 파이프라인을 구성할 수 있지만 중간 연산으로는 어떤 결과도 생성할 수 없다. ● 스트림의 요소는 요청할 때만 계산된다.
  • 53. 필터링과 슬라이싱 ● 프레디케이트로 필터링 ○ 프레디케이트와 일치하는 모든 요소를 포함하는 스트림을 반환한다.
  • 54. 필터링과 슬라이싱 ● 고유 요소 필터링 ○ 고유 요소로 이루어진 스트림을 반환하는 distinct라는 메서드를 지원한다. (중복제거)
  • 55. 필터링과 슬라이싱 ● 스트림 축소 ○ 주어진 사이즈 이하의 크기를 갖는 새로운 스트림을 반환한다. ○ limit(n) 을 호출하면 처음 n개 요소를 선택한 다음 즉시 결과를 반환한다.
  • 56. 필터링과 슬라이싱 ● 요소 건너뛰기 ○ 처음 n개 요소를 제외한 스트림을 반환하는 skip(n) 메서드를 지원한다. ○ n개 이하의 요소를 포함하는 스트림에 skip(n)을 호출하면 빈 스트림이 반환된다.
  • 57. 퀴즈 ● 스트림을 이용해서 처음 등장하는 두 고기 요리를 필터링하시오.
  • 58. 퀴즈 ● 스트림을 이용해서 처음 등장하는 두 고기 요리를 필터링하시오. ● 정답 : List<Dish> dishes = menu.stream() .filter(d -> d.geType() == Dish.Type.MEAT) .limit(2) .collect(toList());
  • 59. 매핑 ● 스트림의 각 요소에 함수 적용하기 ○ 스트림은 함수를 인수로 받는 map 메서드를 지원한다. ○ 인수로 받은 함수를 적용한 결과가 새로운 요소로 매핑된다. ● ex) Dish::getName을 map 메서드로 전달해서 요리명을 추출하는 코드 ● ex) 다른 map 메서드를 연결할 수 있다.
  • 60. 매핑 ● 스트림 평면화 ○ flatMap은 각 배열을 스트림이 아니라 스트림의 콘텐츠로 매핑한다. ● ex) [“Hello”, “World”] 리스트를 [“H”, “e”, “l”, “O”, “W”, “r”, “d”] 로 변환해보자
  • 64. map과 Arrays.stream 활용 ● 배열 스트림 대신 문자열 스트림이 필요할 경우 Arrays.stream을 사용할 수 있다.
  • 65. 검색과 매칭 ● anyMatch ○ 적어도 한 요소와 일치하는지 확일 할때 사용 ● allMatch ○ 모든 요소가 주어진 프레디케이드와 일치하는지 검사 ● noneMatch ○ 주어진 프레디케이와 일치하는 요소가 없는지 확인한다. anyMach, allMatch, noneMatch는 스트림의 쇼트서킷 기법
  • 67. 쇼트서킷 ● 모든 스트림을 처리하지 않고 결과를 반환 할 수 있다. ● 무한한 요소를 가진 스트림을 유한한 크기로 줄일 수 있는 유용한 연산 ○ ex) anyMatch 에서 하나라도 일치하는 결과가 나오면 나머지 결과에 상관없이 True를 반환한다.
  • 68. 검색과 매칭 ● findAny ○ 현재 스트림에서 임의 요소를 반환한다. ● findFirst ○ 현재 스트림에서 첫 번째 요소를 찾아 반환한다. (병렬 실행시 성능 이슈) ● findFirst와 findAny는 병렬성 때문에 사용 된다. ○ 병렬 실행에서는 첫 번째 요소를 찾기 어렵다. 반환 순서가 상관 없다면 병렬 스트림에서는 findAny를 사용하자.
  • 70. Optional ● 값이 존재하는지 확인하고 값이 없을 때 어떻게 처리할 것인지 강제하는 기능 을 제공한다 ○ isPresent 는 Optional이 값을 포함하면 True를 반환하고, 값을 포함하지 않으면 false를 반환한다. ○ ifPresent 는 값이 있으면 주어진 블록을 실행한다. ○ get 은 값이 존재하면 반환하고, 값이 없으면 NoSuchElementException을 일으킨다. ○ orElse 는 값이 있으면 값을 반환하고, 값이 없으면 기본값을 반환한다.
  • 71. 리듀싱 ● 모든 스트림 요소를 처리해서 값으로 도출하는 연산 ○ 메뉴의 모든 칼로리 합계를 구하기 ○ 메뉴의 가장 작은 칼로리 찾기 ○ 메뉴의 가장 높은 칼로리 찾기 ● 초기 값을 지정하지 않으면 Optional 객체 반환한다. ● 내부 반복이 추상화되면서 병렬로 reduce를 실핼 할 수 있다.
  • 74. 숫자형 스트림 ● 기본형 특화 스트림 ○ 스트림 API는 박싱비용을 피할 수 있도록 IntStream, DoubleStream, LongStream을 제공한다. ● 숫자 범위 ○ IntStream과 LongStream은 range와 rangeClose 메서드를 제공한다. ■ range 메서드는 시작값과 종료값이 결과에 포함되지 않는다. ■ rangeClose 메서드는 시작값과 종료값이 결과에 포함된다.
  • 75. 스트림 만들기 ● 값으로 스트림 만들기 ○ 임의의 수를 인수로 받는 정적 메서드 Stream.of를 이용해서 스트림을 만들 수 있다. ○ Stream.empty를 이용해서 스트림을 비울 수 있다. ● 배열로 스트림 만들기 ○ Arrays.stream을 이용해서 스트림을 만들 수 있다. ● 파일로 스트림 만들기 ○ java.nio.file.Files를 이용해서 스트림을 만들 수 있다. ● 함수로 무한 스트림 만들기 ○ Stream.iterate와 Stream.generate를 이용해서 무한 스트림을 만들 수 있다. ■ Stream.iterate는 기존의 결과에 의존해서 순차적으로 연산을 수행 ■ Stream.generate는 새로운 값을 생산한다. ● IntStream을 이용하면 박싱 연산 문제를 해결 할 수 있다.
  • 78. 병렬 스트림 ● 컬렉션에 parallelStream을 호출 하면 병렬 스트림이 생성된다. ● 병렬 스트림을 이용하면 모든 멀티코어 프로세서가 각가의 청크를 처리하도록 할당할 수 있다.
  • 79. 병렬 스트림 ● 숫자 n을 인수로 받아서 1부터 n까지 모든 숫자의 합계를 구하는 코드
  • 80. 병렬 스트림 ● 숫자 n이 커진다면 연산을 병렬로 처리하는 것이 좋을까? ● 병렬로 처리하기 위해서 어디를 수정 해야할까? ● 결과 변수는 어떻게 동기화 해야할까? ● 몇 개의 스레드를 사용해야할까? ● 숫자는 어떻게 생성할까? ● 생성된 숫자는 누가 더할까?
  • 81. 순차 스트림을 병렬 스트림으로 변환하기 ● 순차 스트림에 parallel 메서드를 호출 하면 기존의 함수형 리듀싱 연산이 병렬로 처리된다. 병렬 스트림 ->
  • 82. 순차 스트림을 병렬 스트림으로 변환하기
  • 83. 스트림 성능 측정 ● 병렬화를 이용하면 순차나 반복 형식에 비해 성능이 더 좋아질 것이라 추측했다. ● 병렬화를 이용하면 성능이 더 좋아지는 비교해보자.
  • 84. 스트림 성능 측정 ● 순차 스트림 ● For 루프를 사용
  • 85. 스트림 성능 측정 ● 병렬 스트림
  • 86. 스트림 성능 측정 ● 병렬 스트림이 순차 스트림보다 성능이 나쁘게 나왔다. ○ iterate가 박싱된 객체를 생성하므로 이를 다시 언박싱하는 과정이 필요했다. ○ iterate는 병렬로 실행될 수 있도록 독립적인 청크로 분할하기가 어렵다. ● 리듀싱 과정을 시작하는 시점에 전제 숫자 리스트가 준비 되지 않았음으로 스트림을 병렬로 처리할 수 있도록 청크로 분활할 수 없다. ● 스트림이 병렬로 처리되도록 지시 했지만 순차처리 방식과 크게 다른 점이 없으므로 스레드를 할당하는 오버헤드만 증가 했다.
  • 87. 더 특화된 메서드 사용 ● 멀티코어 프로세서를 활용해서 효과적으로 합계 연산을 병렬로 실행하려면 어떻게 해야할까? ● LongStream.rangeClosed 메서드는 iterate에 비해 다음과 같은 장점을 제공한다. ○ LongStream.rangeClosed는 기본형 long을 직접 사용하므로 박싱과 언박싱 오버헤드가 사라진다. ○ LongStream.rangeClosed는 쉽게 청크로 분할할 수 있는 숫자 범위를 생산한다. ■ 1-20 범위로 숫자를 각각 1-5, 6-10, 11-15, 16-20 범위의 숫자로 분할 할 수 있다.
  • 88. 더 특화된 메서드 사용 ● LongStream.rangeClosed 적용
  • 89. 더 특화된 메서드 사용 ● 순차 스트림 ● 병렬 스트림
  • 90. 더 특화된 메서드 사용 ● 순차 실행보다 빠른 성능을 갖는 병렬 리듀싱을 만들었다. ● 이번에는 실질적으로 리듀싱 연상이 병렬로 실행된다. ● 올바른 자료구조를 선택해야 병렬 실행도 최적의 성능을 발휘할 수 있다. ● 병렬화는 완전 공짜가 아니다. ● 코어 간에 데이터 전송 시간보다 훨씬 오래 걸리는 작업만 병렬로 다른 코어에서 수행하는 것이 바람직하다. ● 병렬화해서 코드 실행 속도를 빠르게 하고싶면 항상 병렬화를 올바르게 사용하고 있는지 확인해야 한다.
  • 91. 병렬 스트림의 올바른 사용법 ● 숫자 n까지의 자연수를 더하면서 공유된 누적자를 바꾸는 코드
  • 92. 병렬 스트림의 올바른 사용법 ● total을 접근 할 때마다 데이터 레이스 문제가 발생 ● 여러 스레드에서 공유하는 객체의 상태를 바꾸는 forEach 블록 내부에서 add 메서드를 호출하면서 문제 발생
  • 93. 병렬 스트림 효과적으로 사용하기 ● 확신이 서지 않는다면 직접 측정하라. ● 박싱을 주의하라 ● 순차 스트림보다 병렬 스트림에서 성능이 떨어지는 연산이 있다. ● 스트림에서 수행하는 전체 파이프라인 연산 비용을 고려하라. ● 소량의 데이터에서는 병렬 스트림 도움 되지 않는다. ● 스트림을 구성하는 자료구조가 적절한지 확인하라. ● 스트림의 특성과 파이프라인의 중간 연상이 스트림의 특성을 어떻게 바꾸는지에 따라 분해 과정의 성능이 달라질 수 있다. ● 최종 연산의 병합 과정 비용을 살펴보라.