반응형
함수형 인터페이스(Functional Interface)
함수형 인터페이스는 Object 클래스의 메서드를 제외하고 추상 메소드를 하나만 가지고 있는 인터페이스이다. 다른 말로 SAM(Single Abstract Method) 인터페이스라고도 한다.
함수형 인터페이스 예시
@FunctionalInterface
public interface RunSomething {
void doIt();
static void printName() {
System.out.println("Kyeongho");
}
default void printAge() {
System.out.println("40");
}
}
- @FunctionalInterface 어노테이션을 붙이면 함수형 인터페이스라 간주하고 추상 메소드가 두 개 이상되면 컴파일 시점에 오류가 발생한다.
- 자바8에서 인터페이스에 static 메소드 정의 가능, default 메소드 정의 가능
→ static 메소드, default 메소드가 몇 개나 존재하던 상관없이 추상 메소드가 하나이면 함수형 인터페이스이다.
함수형 인터페이스 사용 예시
public class App
{
public static void main( String[] args ) {
// 익명 내부 클래스 anonymous inner class
RunSomething runSomething = new RunSomething() {
int baseNumber = 10;
@Override
public int doIt(int number) {
return number + 10;
}
};
// 람다 표현식을 이용하여 코드를 간결하게
RunSomething runSomthing_lambda = (number) -> number + 10;
RunSomething runSomthing_lambda2 = (number) -> {
System.out.println("Hello");
System.out.println("Kyeongho");
return number + 10;
};
}
}
자바에서 함수형 프로그래밍
함수형 인터페이스를 구현한 익명 객체는 결국 오브젝트다. 따라서 함수가 함수를 리턴하거나 함수가 함수를 파라미터를 받는등 다양한 함수형 프로그래밍이 가능하다. 다만 함수형 프로그래밍을 한다하면 다음과 같은 사항을 잘 준수하여야함. !특히 순수 함수를 주의하여 준수할 것
- 함수를 First class object로 사용할 수 있다.
- 순수 함수 (Pure function)
- 사이드 이팩트가 없다. (함수 밖에 있는 값을 변경하지 않는다.)
- 상태가 없다. (함수 밖에 있는 값을 사용하지 않는다.)
- 고차 함수 (Higher-Order Function)
- 함수가 함수를 매개변수로 받을 수 있고 함수를 리턴할 수도 있다.
- 불변성
자바에서 제공하는 함수형 인터페이스
Java가 기본으로 제공하는 함수형 인터페이스
- java.lang.funcation 패키지 → 자바에서 미리 정의해둔 자주 사용할만한 함수 인터페이스
- Function
- BiFunction
- Consumer
- Supplier
- Predicate
- UnaryOperator
- BinaryOperator
좀 더 자세히 살펴보자.
Function<T, R>
- T 타입을 받아서 R 타입을 리턴하는 함수 인터페이스
- R apply(T t)
- 함수 조합용 메소드
- andThen
- compose
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
- compose: before 메서드 실행 후 결과를 받아서 현재 메소드 실행. 제네릭 타입은 처음 input과 마지막 output의 타입이다. 즉 ,메서드를 순서대로 실행시키기 위한 함수
- andThen: compose와 반대로 현재 메소드를 실행 후 매게 변수로 받은 람다를 실행
- identity: 자신의 값을 그대로 리턴하는 스테틱 메서드
ompose , andThen 차이점
andThen()과 compose()의 차이점은 어떤 함수형 인터페이스부터 먼저 처리하느냐의 차이가 있다.
인터페이스A.compose(인터페이스B);
B실행 -> A실행
인터페이스A.andThen(인터페이스B);
A실행 -> B실행
BiFunction<T,U,R>
- 두 개의 값(T, U)를 받아서 R 타입을 리턴하는 함수 인터페이스
- R apply(T t, U u)
- 함수 조합용 메소드
- andThen
@FunctionalInterface
public interface BiFunction<T, U, R> {
R apply(T t, U u);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t, U u) -> after.apply(apply(t, u));
}
}
- andThen: 현재 메소드를 실행 후 매게 변수로 받은 람다를 실행
Consumer<T>
- T 타입을 받아서 아무값도 리턴하지 않는 함수 인터페이스
- void Accept(T t)
- 함수 조합용 메소드
- andThen
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
- andThen: Consumer 인터페이스는 처리 결과를 리턴하지 않기 때문에 andThen() 디폴트 메서드는 함수형 인터페이스의 호출 순서만을 정한다.
Supplier<T>
- T 타입의 값을 제공하는 함수 인터페이스
- T get()
@FunctionalInterface
public interface Supplier<T> {
T get();
}
- get: 제네릭으로 전달받은 타입으로 값을 전달
Predicate<T>
- T 타입을 받아서 boolean을 리턴하는 함수 인터페이스
- boolean test(T t)
- 함수 조합용 메소드
- And
- Or
- Negate
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
- and: 인자로 받는 다른 Predicate의 람다 수행 내용과 , 자기 자신의 람다 수행 내용을 &&연산
- or: 인자로받는 다른 Predicate의 람다 수행내용과 , 자기자신의 람다 수행내용을 ||연산
- negate: 람다 수행 내용을 ! 연산
UnaryOperator
- Function의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수
인터페이스
BinaryOperator
- BiFunction의 특수한 형태로, 동일한 타입의 입렵값 두개를 받아 리턴하는 함수
인터페이스
참고
반응형
'Study > java' 카테고리의 다른 글
반복적인 DTO 변환 작업을 한 번에 정의! MapStruct 기본 정리 (0) | 2021.03.07 |
---|---|
람다 표현식(Lambda Experessions) 정리 (3) | 2021.02.08 |
(펌)Java8 Optional 의 ifPresent 활용 (0) | 2020.10.04 |
Java Stream(2) - 가공하기 및 결과 만들기 (0) | 2020.07.26 |
Java Stream(1) - 기본 개념 및 생성하기 (0) | 2020.07.22 |