함수형(Functional) 인터페이스 와 람다(Lambda)표현식
- 함수형 인터페이스는 추상 메소드가 오직 하나인 인터페이스를 말한다. (defult method 또는 static method는 여러개 존재해도 된다.)
- @FunctionalInterface 어노테이션을 사용한다. -> 해당 인터페이스가 함수형 인터페이스 조건에 맞는지 검사해준다. (인터페이스 검증 및 유지보수를 위해 붙여주는 것이 좋다.)
- 자바의 람다식은 함수형 인터페이스로만 접근이 가능하다
=> 이러한 함수형 인터페이스를 사용하는 이유는 람다식을 사용하기 위함이고, 람다식을 사용 하는 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함이다.
@FunctionalInterface
public interface FunctionalInterface {
public abstract void print(String text);
}
FunctionalInterface func = text -> System.out.println(text);
func.print("hi FunctionalInterface");
// 출력 값 : hi FunctionalInterface
✅ JAVA에서 기본적으로 제공하는 Functional Interface
함수형 인터페이스 | Descripter | Method |
Predicate | T -> boolean | boolean test(T t) |
Consumer | T -> void | void accept(T t) |
Supplier | ( ) -> T | T get() |
Function<T,R> | T -> R | R apply(T t) |
Comparator | (T, T) -> int | int compare(T o1, T o2) |
Runnable | ( ) -> void | void run() |
Callable | ( ) -> T | V call() |
이 외에 함수형 인터페이스 java.util.function
Predicate
: 인자를 하나 받아서 boolean 타입을 리턴한다.
람다식으로는 T -> boolean 로 표현한다..
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}
// T -> boolean
Predicate<String> startsWithKim = s -> s.startsWith("kim");
System.out.println(startsWithKim.test("kimHappy"));
// 출력값 : true
Consumer
: 인자 하나를 받고 아무것도 리턴하지 않는다.
람다식으로는 T -> void 로 표현한다.
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
// T -> void
Consumer<String> printString = text -> System.out.println("hi " + text);
printString.accept("Consumer");
// 결과 값 : hi Consumer
Supplier
: 아무런 인자를 받지 않고 T 타입의 객체를 리턴한다.
람다식으로는 ( ) -> T 로 표현한다.
@FunctionalInterface
public interface Supplier<T> {
T get();
}
// ( ) -> T
Supplier<String> getString = () -> "hi Supplier!";
String str = getString.get();
System.out.println(str);
// 결과값 : hi Supplier!
Function
: T 타입 인자를 받아서 R 타입을 리턴한다.
람다식으로는 T -> R 로 표현한다.
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
// T -> R
Function<Integer, Integer> multiply = value -> value * 2;
Integer result = multiply.apply(3);
System.out.println(result);
// 결과값 : 6
Comparator
: T 타입 인자 두개를 받아서 int 타입을 리턴한다.
람다식으로는 (T, T) -> int 로 표현한다.
@FunctionalInterface
public interface Comparator<T> {
int compare(T o1, T o2);
}
// (T, T) -> int
Comparator<Integer> numAdd = (num1, num2) -> num1 + num2;
System.out.println(numAdd.compare(10,20));
// 출력값 : 30
Runnable
: 아무런 객체를 받지 않고 리턴도 하지 않는다.
람다식으로는 ( ) -> void 로 표현한다.
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
// 람다식 : ( ) -> void
Runnable runnable = () -> System.out.println("hi runnable!");
runnable.run();
Callable
: 아무런 인자를 받지 않고 T 타입 객체를 리턴한다.
람다식으로는 ( ) -> T 로 표현한다.
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
// ( ) -> T
Callable<String> stringCallable = () -> "hi Colllable";
System.out.println(stringCallable.call());
// 출력값 : hi Colllable
Callable VS Supplier
: 아무런 인자를 받지 않고 T 타입 객체를 리턴한다.
둘의 차이는 Callable는 결과를 반환하고 예외를 throw할 수 있고, 다른 스레드에 의해 인스턴스가 잠재적으로 실행되는 클래스를 위해 설계 되었다. 반면 Supplier는 그저 값은 제공하는 기능을 한다.
=> 다른 스레드를 처리하지 않거나 작업에서 예외가 발생할 가능성이 매우 낮은 경우 외에는 Callable 사용을 권장한다.
'JAVA > Modern JAVA' 카테고리의 다른 글
[JAVA 8] 날짜/시간 표현 (Instant, ZonedDateTime, LocalDateTime, Period) (0) | 2022.11.16 |
---|---|
[JAVA 8] 분할 가능한 Iterator인 Spliterator 인터페이스 (0) | 2022.11.01 |