Open youngkimi opened 3 months ago
함수형 인터페이스를 새로 구현하기 보다는 표준 함수형 인터페이스를 활용하라.
함수형 인터페이스
표준 함수형 인터페이스
템플릿 메서드 패턴
정적 팩터리
생성자
LinkedHashMap
protected
removeEldestEntry
Map
put()
// 상위 클래스의 removeEldestEntry를 재정의. // Entry Size가 100을 넘으면, true를 반환할 것이다. protected boolean removeEldestEntry(Map.Entry<K, V> eldest) { return size() > 100; }
Map.Entry<K, V> eldest
boolean
size()
인스턴스 메서드
@FunctionalInterface interface EldestEntryRemovalFunction<K, V> { boolean remove(Map<K, V> map, Map.Entry<K, V> eldest); }
Predicate
EldestEntryRemovalFunction
BiPredicate<Map<K, V>, Map.Entry<K, V>>
java.util.functional
UnaryOperator
BinaryOperator
다 외우기에는 수도 많고 규칙성도 부족하다.
기본 인터페이스는 Primitive Type인 int, long, double용으로 각 3개씩 변형이 생긴다.
int
long
double
기본 인터페이스 앖에 해당 기본 타입
Function 인터페이스의 변형은 입력과 반환값의 타입이 항상 다르므로 기본 타입을 반환하는 변형이 총 9개 (3*3) 더 있다. (기본 변형의 접두사는 입력타입을 나타냄)
Function
입력타입
SrcToRes
LongToIntFunction
ToResult
ToLongFunction<int[]>
인수를 두 개씩 받는 인터페이스 변형 : BiPredicate<T, U>, BiFunction<T, U, R>, BiConsumer<T, U>
BiPredicate<T, U>
BiFunction<T, U, R>
BiConsumer<T, U>
기본 타입(int, long, double)으로 반환하는 BiFunction의 변형 : ToIntBiFunction<T, U>
ToIntBiFunction<T, U>
객체 참조와 기본 타입(int, long, double) 하나 받는 변형 : ObjIntConsumer<T>
ObjIntConsumer<T>
boolean을 반환하는 Supplier : BooleanSupplier
BooleanSupplier
표준 함수형 인터페이스에 박싱된 기본 타입을 넣어 사용하지는 말자. 동작은 하지만, 계산량이 많으면 성능이 느려질 수 있다. (item 61)
아래 조건 중 하나 이상을 만족한다면 고민해보아야 한다.
Comparator<T>를 떠올려보자.
Comparator<T>
ToIntBiPredicate<T, U>
@FunctionalInterface
@Override를 사용하는 이유와 비슷하다.
@Override
다중 정의
ExecutorService
submit()
Callable<T>
Runnable<T>
자바가 람다를 지원함을 생각하고 API를 설계하라.
-
Chapter : 7. 람다와 스트림
Item : 44. 표준 함수형 인터페이스를 사용하라
Assignee : youngkimi
🍑 서론
함수형 인터페이스
를 새로 구현하기 보다는표준 함수형 인터페이스
를 활용하라.템플릿 메서드 패턴
보다는, 함수 객체를 받는정적 팩터리
나생성자
를 제공하는 것이 보다 현대적이다.🍑 본론
LinkedHashMap
protected
메서드인removeEldestEntry
를 재정의하면 캐시로 사용할 수 있다.Map
에 새로운 키를 추가하는put()
메서드는 이 메서드를 호출하여 true가 반환되면 맵에서 가장 오래된 원소를 제거한다.LinkedHashMap
을 오늘날 다시 구현한다면, 함수 객체를 받는 정적 팩터리나 생성자를 제공했을 것이다.표준 함수형 인터페이스를 사용해라
removeEldestEntry
선언을 보면, 이 함수 객체는 Entry인Map.Entry<K, V> eldest
을 받아boolean
을 반환할 것 같은데, 꼭 그렇지는 않다.size()
를 호출해 맵 안의 원소 수를 알아내는데,removeEldestEntry
가인스턴스 메서드
기에 가능한 방식이다.인스턴스 메서드
가 아니다. 팩터리나 생성자를 호출할 때는 맵의 인스턴스가 존재하지 않기 때문이다. 맵은 자기 자신도 함수 객체에 건네줘야 한다.Predicate
인터페이스는 predicate를 조합하는 메서드를 제공한다.EldestEntryRemovalFunction
대신 표준 인터페이스인BiPredicate<Map<K, V>, Map.Entry<K, V>>
를 사용할 수 있다.자주 사용하는 기본 인터페이스 6가지
java.util.functional
에는 43개의 인터페이스가 담겨 있다.Operator(Unary, Binary)
UnaryOperator
,BinaryOperator
로 나뉜다.Predicate
boolean
을 반환하는 함수를 말한다.Function
Supplier
Consumer
기본 인터페이스 변형
다 외우기에는 수도 많고 규칙성도 부족하다.
기본 인터페이스는 Primitive Type인
int
,long
,double
용으로 각 3개씩 변형이 생긴다.기본 인터페이스 앖에 해당 기본 타입
Function
인터페이스의 변형은 입력과 반환값의 타입이 항상 다르므로 기본 타입을 반환하는 변형이 총 9개 (3*3) 더 있다. (기본 변형의 접두사는입력타입
을 나타냄)UnaryOperator
이므로, Function 인터페이스의 변형은 입력, 결과 타입이 항상 다르다.SrcToRes
접두사가 붙은Function
인터페이스는 6가지가 있다.LongToIntFunction
int
,long
,double
인 변형들. 앞서와는 달리 입력을 매개변수화하고 접두어로ToResult
를 사용한다.ToLongFunction<int[]>
인수를 두 개씩 받는 인터페이스 변형 :
BiPredicate<T, U>
,BiFunction<T, U, R>
,BiConsumer<T, U>
기본 타입(
int
,long
,double
)으로 반환하는 BiFunction의 변형 :ToIntBiFunction<T, U>
객체 참조와 기본 타입(
int
,long
,double
) 하나 받는 변형 :ObjIntConsumer<T>
boolean
을 반환하는 Supplier :BooleanSupplier
표준 함수형 인터페이스에 박싱된 기본 타입을 넣어 사용하지는 말자. 동작은 하지만, 계산량이 많으면 성능이 느려질 수 있다. (item 61)
함수형 인터페이스
를 직접 구현해야 하는 경우아래 조건 중 하나 이상을 만족한다면 고민해보아야 한다.
Comparator<T>
를 떠올려보자.ToIntBiPredicate<T, U>
와 동일하다.Comparator<T>
를 자바 라이브러리에 추가할 당시ToIntBiPredicate<T, U>
가 있었음에도 사용하지 않았다. (않아야 했다.)직접 만든 함수형 인터페이스에는 항상
@FunctionalInterface
를 사용하라@Override
를 사용하는 이유와 비슷하다.함수형 인터페이스를 API에서 사용할 때의 주의점
다중 정의
하지 말라.ExecutorService
의submit()
메서드는Callable<T>
,Runnable<T>
를 받는 경우를다중 정의
한다.🍑 결론
자바가 람다를 지원함을 생각하고 API를 설계하라.
Referenced by
-