///Modern Java in Action / 한빛미디어
1장. 자바 8, 9, 10, 11 : 무슨 일이 일어나고 있는가?
* Stream API
- Stream 이란 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임
- 스트림을 이용하면 에러를 자주 일으키며 멀티코어 CPU 를 이용하는 것보다 비용이 훨씬 비싼 키워드 sychronized 를 사용하지 않아도 된다.
- external iteration : for-each 와 같은 루프를 이용해 각 요소를 반복하면서 작업을 수행
- internal iteration : Stream API 에서는 라이브러리 내부에서 모든 데이터가 처리됨
* pure/side-effect-free/stateless 함수
- 공유된 가변 데이터에 접근하지 않아서 다른 코드와 동시에 실행하더라도 안전하게 실행할 수 있는 함수
* interface 의 default 메소드
-
* 자바의 함수
- 메소드 개념에 더불어 수학적인 함수처럼 사용되며 부작용을 일으키지 않는 함수를 의미
2장. 동작 파라미터화 코드전달하기
* Behavior Parameterization (동작 파라미터화)
- 실행 동작 즉, 메소드를 가진 객체를 파라미터로 전달하는 것을 의미
3장. 람다 표현식
* 람다
- 메소드로 전달할 수있는 익명 함수를 단순화한 것
- 메소드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다.
- Parameter List, 화살표, Body로 구성
- Expression-style : (parameters) -> expression
- Block-style : (parameters) -> { statements; }
- 함수형 인터페이스 문맥에서 사용할 수 있다
* 함수형 인터페이스
- 하나의 추상 메소드를 지정하는 인터페이스
- @FunctionalInterface 를 붙이면 지정 가능하다
* Function Descriptor
- 람다 표현식의 시그니처를 서술하는 메소드
* Predicate
- Generic 타입 T 객체를 받아서 true 나 false 를 반환하는 함수
- @FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
- @FunctionalInterface
public interface BiPredicate<T, U> {
boolean test(T t, U u);
}
* Consumer
- Generic 타입 T 객체를 받아서 void 를 반환하는 함수
- @FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
- @FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
* Function
- Generic 타입 T 객체를 받아서 Generic 타입 R 객체를 반환하는 함수
- @FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
- @FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
}
* Supplier
- 객체를 전달 받지 않고 Generic 타입 T 객체를 반환하는 함수
- @FunctionalInterface
public interface Supplier<T> {
T get();
}
* UnaryOperator
- Generic 타입 T 객체를 받아서 Generic 타입 T 객체를 반환하는 단항 연산자 함수
- @FunctionalInterface
public interface UnaryOperator<T> {
T apply(T t);
}
* BinaryOperator
- Generic 타입 T 객체 2개를 받아서 Generic 타입 T 객체를 반환하는 이항 연산자 함수
- @FunctionalInterface
public interface BinaryOperator<T> {
T apply(T t1, T t2);
}
* 기본형 특화 함수형 인터페이스
- Generic 내부 구현상 기본형 타입은 사용이 불가하기에 Integer, Long 등의 Wrapper 클래스를 이용하면 AutoBoxing 이 동작한다. 이러한 Cost 를 줄이기 위해 기본형 특화 함수형 인터페이스를 제공한다
- IntPredicate, LongPredicate, DoublePredicate, ObjIntConstumer<T>, ToLongBiFunction<T, U> 등
* 형식 검사
- 람다가 사용되는 Context 를 이용해서 람다의 Type (즉, Target Type) 을 추론하는 것
- 입력 파라미터와 출력 타입을 추론하여 함수형인터페이스를 추론
- 다이아몬드 연산자 (<>)도 Context 를 사용해 추론한다
* Free Variable (자유 변수)
- Parameter 로 넘겨진 변수가 아닌 외부 변수
* Capturing Lambda (람다 캡쳐링)
- Body 에서 인스턴스 변수와 정적 변수만 자유롭게 캡처할 수 있다
- 기본형 타입의 경우 final 로 선언되어 있어야 한다
- 이러한, 지역변수 제약이 있는 것은 인스턴스 변수는 Heap 에 생성되는 반면에 지역변수는 Stack 에 위치하기 때문
* method reference (::)
- 메소드를 가진 객체를 값으로 전달할 때 사용
- 정적 메소드 참조
(args) -> ClassName.staticMethod(args)
ClassName::staticMethod
- 다양한 형식의 인스턴스 메서드 참조
(arg0, rest) -> arg0.instanceMethod(rest)
ClassName::instanceMethod
- 기존 객체의 인스턴스 메서드 참조
(args) -> expr.instanceMethod(args)
expr::instanceMethod
* 생성자 참조
- new 키워드를 이용해서 생성자 참조를 만들 수 있다
- Supplier<ClassName> supplier = ClassName::new;
3.7부터 보기