자바 8 새로운 기능
- 스트림API
- 메서드에 코드를 전달하는 기법
- 인터페이스의 디폴트 메서드
스트림 API 덕분에 두 가지 기능 제공
- 메서드에 코드를 전달하는 간결 기법(메서드 참조와 람다)
- 인터페이스의 디폴트 메서드 존재
1.2.2 스트림 처리
스트림이란 ?
- 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임
- 스트림 API가 조립 라인처럼 어떤 항목을 연속으로 제공하는 어떤 기능이라고 생각하기
스트림 API 핵심은?
- 기존에 한 번에 한 항목을 처리했지만 데이터베이스 질의처럼 고수준으로 추상호화해서 일련의 스트림으로
만들어 처리할 수 있다.
- 스트림 파이프라인을 이용해 입력 부분을 여러 CPU 코어에 쉽게 할당할 수 있다
(스레드라는 복잡한 작업을 사용하지 않으면서도 공짜로 병렬성을 얻을 수 있다.)
1.2.3. 동작 파라미터화로 메서드에 코드 전달하기
- 자바 8에 추가된 두번째 프로그램 개념은 '코드 일부를 API로 전달하는 기능'
- 자바 8에서는 메서드(우리 코드)를 다른 메서드의 이눗로 넘겨주는 기능을 제공한다. 이러한 기능을 '동작 파라미터화'라고 한다.
1.2.4 병렬성과 공유 가변 데이터
- 스트림 메서드로 전달하는 코드의 동작 방식을 바꾸어야 병렬성을 얻는다.
- '안전하게 실행할 수 있는 코드를 만드려면 공유된 가변 데이터에 접근하지 않아야 한다.
(공유된 변수나 객체가 있으면 병렬성에 문제가 발생한다.)
1.2.5 자바가 진화해야하는 이유
- 언어는 하드웨어나 프로그래머 기대의 변화에 부응하는 방향으로 변화해야 한다.
- 자바는 계속 새로운 기능을 추가하면서 인기 언어의 자리를 유지하고 있다.
- 그러나, 자바 8의 새로운 기능에 관심을 가짐으로써 스스로 자바 프로그래머로서의 삶을 유지할 수 있도록 자신을 보호할 수 있다.
자바 8에서 추가된 새로운 개념
1.3 자바 함수
- 함수를 값처럼 취급하는 특징은 어떤 장점이 있는가?
1.3.1 메서드와 람다를 일급 시민으로
- '메서드 참조'라는 새로운 기능
- '메서드 참조'는 메서드를 값으로 사용하라는 의미
- 람다 문법 형식으로 구현된 프로그램 = 함수형 프로그래밍 = 함수를 일급값으로 넘겨주는 프로그램을 구현한다
- 핵심은 자바8은 메소드를 전달할 수 있다는 것이다.
프레디케이트(predicate)란 ?
- 수학에서는 인수로 값을 받아 true나 false를 반환하는 함수를 프레디케이트라고 한다.
- Predicate<Apple>
- public interface Predicate<T> {
boolean test(T t);
}
1.3.3 메서드 전달에서 람다로
- filterApples(inventory, (Apple a) -> GREEN.equals(a.getColor()) );
- filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
- filterApples(inventory, (Apple a) -> a.getWeight() < 80 || RED.equals(a.getColor()) );
- 한 번만 사용할 메서드는 따로 정의를 구현할 필요가 없다. (코드를 애써 찾을 필요가 없을 정도로 더 짧고 간결하다)
- 람다가 몇 줄 이상으로 길어진다면, 익명 람다보다는 코드가 수행하는 일을 잘 설명하는 이름을 가진 메서드를 정의하고,
- 메서드 참조를 활용하는 것이 바람직하다.
- 라이브러리 filter를 이용하면 filterApples 메서드를 구현할 필요가 없다
- filter(inventory, (Apple a) -> a.getWeight() > 150 );
- 그러나, 병렬성이라는 중요성 때문에 설계 포기하였다.
- 자바 8에서는 filter와 비슷한 동작을 수행하는 연산집합을 포함하는 새로운 스트림 API를 제공한다.
- 컬렉션과 스트림간에 변환할 수 있는 메서드(map, reduce 등)도 제공한다.
1.4 스트림
- 중첩된 제어 흐름 문장이 많은 경우, 한번에 코드를 이해하기 어렵다.
- 스트림 API를 이용하면 다음처럼 문제를 해결할 수 있따.
- import static java.util.stream.Collectors.groupingBy;
- Map<Currency, List<Transaction>> transactionsByCurrencies =
transactions.stream()
.filter((Transaction t) -> t.getPrice() > 1000) // 고가의 트랜잭션 필터링
.collect(groupingBy(Transaction::getCurrency)); // 통화로 그룹화함
1.4.1 멀티스레딩은 어렵다
- 이전 자바 버전에서 제공하는 스레드 API로 멀티스레딩 코드를 구현해서 병렬성을 이용하는 것은 쉽지 않다.
- 스레드를 잘 제어하지 못하면 원치 안흔 방식으로 데이터가 바뀔 수 있따.
- 자바 9은 스트림 API(java.util.stream)로 '컬렉션을 처리하면서 발생하는 모호함과 반복적인 코드 문제' , '멀티코어 활용 어려움'이라는
두가지 문제를 모두 해결했다.
- 자주 반복되는 패턴으로 주어진 조건에 따라 데이터를 필터링하거나, 데이터를 추출하거나, 데이터를 그룹화 하는 등의 기능이 있다.
- 이러한 동작들을 쉽게 병렬화할 수 있다.
- *포킹단계(forking step) : 두 CPU를 가진 환경에서 리스트를 필터링할 때 한 CPU는 리스트의 앞부분을 처리하고, 다른 CPU는 리스트의 뒷부분을
처리하도록 요청할 수 있다.
- 컬렉션과 스트림 차이
- 컬렉션은 어떻게 데이터를 저장하고 접근할지에 중점을 두는 반면 ,
- 스트림은 데이터 어떤 계산을 할 것인지 묘사하는 것에 중점을 둔다는 점을 기억하자.
- 스트림은 스트림 내의 요소를 쉽게 병렬로 처리할 수 있는 환경을 제공한다는 것이 핵심이다.
- 컬렉션을 필터링할 수 있는 가장 빠른 방법 -> 컬렉션을 스트림으로 바꾸고 -> 병렬로 처리한 다음에 -> 리스트로 다시 복원한다.
- 순차 처리 방식과 병렬처리 방식의 코드 차이점
- 다음은 순차 처리 방식의 코드다.
- import static java.util.stream.Collectors.toList;
List<Apple> heavyApples =
inventory.stream().filter((Apple a) -> a.getWeight() > 150 ).collect(toList());
- 다음은 병렬 처리 방식의 코드다.
- import static java.util.stream.Collectors.toList;
List<Apple> heavyApples =
inventory.parallelStream().filter((Apple a) -> a.getWeight() > 150 ).collect(toList());
P.59 예가 이해가 안간다.
Collection.sort는 사실 ~ 수행하는 것이 적절하다.
1.5 디폴트 메서드와 자바 모듈
- 인터페이스를 쉽게 바꿀 수 있도록 디폴트 메서드를 지원한다.
- 디폴트 메서드는 특정 프로그램을 구현하는데 도움을 주는 기능이 아니라 미래에 프로그램이 쉽게 변화할 수 있는 환경을 제공하는 기능
- 뒷 부분이 이해가 안간다.
1.6 함수형 프로그래밍에서 가져온 다른 유용한 아이디어
- 핵심 아이디어 2가지는 다음과 같다.
- 메서드와 람다를 일급값으로 사용하는 것
- 가변 공유 상태가 없는 병렬 실행을 이용해서 효율적이고 안전하게 함수나 메서드를 호출할 수 있다는 것
- 명시적으로 서술형의 데이터 형식을 이용해 null을 회피하는 기법 ?
- 자바 8에서는 NullPointer 예외를 피할 수 있도록 Optional<T> 클래스를 제공한다.
- Optional<T>는 값을 갖거나 갖지 않을 수 있는 컨테이너 객체다.
- Optional<T>는 값이 없는 상황을 어떻게 처리할지 명시적으로 구현하는 메서드를 포함하고 있다.
- 그래서, Optional<T>를 사용하면 NullPointer 예외를 피할 수 있다.
'모던자바인액션' 카테고리의 다른 글
TIL_모던자바인액션_3_230202 (0) | 2023.02.02 |
---|---|
TIL_모던자바인액션_2_230131-230202 (0) | 2023.01.31 |