자바가 기본적으로 제공해주는 인터페이스
입출력 값의 유무, 사용기능등에 따라서 다양한 함수형 인터페이스들을 사용 할 수 있다.
기본적인 구현
import java.util.function.Function;
public class Plus implements Function<Integer, Integer>{
@Override
public Integer apply(Integer t) {
return t+1;
}
}
함수형 인터페이스를 사용 할 시 본래는 클래스를 함수형 인터페이스를 구현하는 형식으로 사용한다.
위의 예제는 Function이라는 기본제공 함수형 인터페이스를 사용하여 Plus라는 클래스를 생성하는 예제이다.
이는 메서드가 한개인 함수형 인터페이스이므로 람다식을 써서 구현 할 수 있다.
람다식을 통해 구현 할 시 클래스 파일을 새로 만들 필요가 없으며 정해진 함수 원하는 부분에 구현하여 객체로 표현할 수 있게 된다.
이를 통해 함수형 프로그래밍을 가능하도록 한다.
Function<T,R>
public static void main(String[] args) {
Function<Integer, Integer> Plus = (a)-> a+3;
Function<Integer, Integer> Multiple = (a)-> a*3;
Function<Integer, Integer> MultiplePlus = Plus.andThen(Multiple);
Function<Integer, Integer> MultiplePlus2 = Plus.compose(Multiple);
System.out.println(Plus.apply(1)); //1+3
System.out.println(Multiple.apply(1)); //1*3
System.out.println(MultiplePlus.apply(1)); //(1+3)*3
System.out.println(MultiplePlus2.apply(1)); // (1*3)+3
}
Function<T,R> : 하나의 입력값과 하나의 출력값
T와 R에서 입력과 출력의 형태를 정의 할 수 있다.
이렇게 만들어진 함수는 Compose와 andThen을 활용해서 구현된 함수끼리 연결 할 수 있다.
andThen : 본 함수를 먼저 실행한 후 해당 값을 파라미터 함수를 실행한다.
Compose는 : 파라미터 함수를 먼저 실행하고 해당값으로 본 함수를 실행한다.
apply를 통해 실행한다.
Consumer<T>
public static void main(String[] args) {
Consumer<Integer> Print1 = (i) -> System.out.println("in");
Consumer<Integer> Print2 = (i) -> System.out.println("out");
Consumer<Integer> Print3 = Print1.andThen(Print2);
Print1.accept(1); //in
Print2.accept(1); //out
Print3.accept(1); //in out
}
Consumer<T>: 하나의 입력값 출력 없음
입력값은 존재하나 출력값은 존재하지 않는 함수이다.
Accept를 통해 실행하며 andThen을 통해 함수를 조합 할 수 있다.
Supplier<T>
public static void main(String[] args) {
Supplier<Integer> Sup = ()->3;
System.out.println(Sup.get());
}
Supplier<T> : 입력값은 없고 출력값만 존재 한다.
get을 통해 실행하며 다른 함수와 조합 할 수 없다.
Runnable
public static void main(String[] args) {
Runnable a = ()->System.out.println("run");
a.run(); //run
}
Runnable : 입력값도 없고 출력값도 없다.
다른 함수와 조합 할 수 없다.
위의 4개의 함수형 인터페이스를 정리하면 다음과 같다.
출력 O | 출력 X | |
입력 O | Function<T,R> | Consumer<T> |
입력 X | Supplier<T> | Runnable |
* 입력값이 존재하는 경우 함수를 조합 할 수 있다.
BiFunction<T, U, R>
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> Plus = (a,b) -> a+b;
System.out.println(Plus.apply(1, 2)); //1+2
}
BiFunction<T,U,R> : 두개의 입력값 하나의 출력값
T,U 에 입력값의 형태를 정의 하며 이를 R로 리턴하는 형태의 함수형 인터페이스이다.
apply를 통해 실행한다.
Predicate<T>
public static void main(String[] args) {
Predicate<Integer> Pre1 = (t) -> {
if(t>0)
{
return true;
}
else {
return false;
}
};
Predicate<Integer> Pre2 = (t) -> {
if(t<2)
{
return true;
}
else {
return false;
}
};
Predicate<Integer> Pre3 = Pre1.and(Pre2);
Predicate<Integer> Pre4 = Pre1.or(Pre2);
Predicate<Integer> Pre5 = Pre1.negate();
System.out.println(Pre1.test(1)); //true
System.out.println(Pre1.test(-1)); //false
System.out.println(Pre2.test(1)); //true
System.out.println(Pre2.test(3)); //false
System.out.println(Pre3.test(1)); //true
System.out.println(Pre3.test(4)); //false
System.out.println(Pre4.test(4)); //true
System.out.println(Pre4.test(-1)); //true
System.out.println(Pre5.test(1)); //false
}
Predicate<T> : 입력값 T에 대해서 Test를 수행하여 Boolean값을 출력한다.
Test를 통해 실행하며
And,Or을 통해 다른 Predicate와 조합이 가능하며
Negate를 통해 값을 반대로 리턴 할 수 있다.
UnaryOperator<T>
public static void main(String[] args) {
UnaryOperator<Integer> Plus = (num) -> num+1;
System.out.println(Plus.apply(1));
}
UnaryOperator<T> : Function의 특수한 형태로 입력값과 출력값의 타입이 동일한 경우 사용한다.
Function과 같은 기능을 가지고 있다.
BinaryOperator<T>
public static void main(String[] args) {
BinaryOperator<Integer> Plus = (a,b) -> a+b;
System.out.println(Plus.apply(1,2));
}
BinaryOperator<T> : BiFunction의 특수한 형태로 입력값과 출력값의 타입이 동일한 경우 사용한다.
BiFunction과 같은 기능을 가지고 있다.
'Programing Language > JAVA' 카테고리의 다른 글
AutoBoxing vs UnBoxing (0) | 2021.02.21 |
---|---|
Platform Independent Language (0) | 2021.02.21 |
JAVA Stream API -1 (기본 사용법) (0) | 2021.01.21 |
Effective Final과 lambda expression의 Scope (0) | 2020.08.16 |
함수형 인터페이스와 람다 표현식 (0) | 2020.08.11 |