함수형 인터페이스(Functional Interface)는 오직 1개의 추상 메소드를 갖는 인터페이스를 말한다.
public interface FunctionalInterface{
// abstract 메서드는 무조건 하나만!!
public abstract void doSomething(String text);
// default는 있어도 무관
default void a(){
...
}
// static도 괜츈
static void b(){
...
}
}
함수형 인터페이스를 사용하는 이유는 자바의 람다식은 함수형 인터페이스로만 접근이 되기 때문이다.
public interface FunctionalInterface {
public abstract void doSomething(String text);
}
...
// 1번 코드
FunctionalInterface func = new FunctionalInterface() {
@Override
public void doSomething(String text) {
System.out.println(text);
}
};
func.doSomething("hello world");
// 2번 코드
FunctionalInterface func2 = text -> System.out.print(text);
func2.doSomething("hello world");
java 8 에서는 함수형 인터페이스를 제공해주고 있다.
List<String> lists = Arrays.asList("1", "2", "3", "4", "5");
lists.forEach(num -> System.out.println(num));
lists.forEach(System.out::println);
다만 개인적으로 이중 콜론이 익숙하지 않은 상태에서 코드를 보면 가독성 면에서 썩 좋을 것 같진 않다..
Functional Interface는 @FunctionalInterface 어노테이션을 사용하는데, 이 어노테이션은 해당 인터페이스가 함수형 인터페이스 조건에 맞는지 검사해준다.
@FunctionalInterface 어노테이션이 없어도 함수형 인터페이스로 동작하고 사용하는 데 문제는 없지만, 인터페이스 검증과 유지보수를 위해 붙여주는 게 좋다.
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
...
}
//같은 타입이면서 같은 값을 반환하는 것을 identity function이라 한다.
Function<String, Integer> toInt = Integer::parseInt;
final Integer number = toInt.apply("100");
System.out.println(number);
final Function<Integer, Integer> identity = Function.identity();
final Function<Integer, Integer> identity2 = t -> t;
System.out.println(identity.apply(999));
System.out.println(identity2.apply(999));
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
...
}
final Consumer<String> print = System.out::println;
final Consumer<String> greetings = s -> System.out.println(s + " World");
print.accept("jaja");
greetings.accept("Hello");
greetings.accept("CAD");
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
...
}
Predicate<Integer> isPositive = i -> i > 0;
System.out.println(isPositive.test(1));
System.out.println(isPositive.test(0));
System.out.println(isPositive.test(-1));
true
false
false
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
// Supplier<String> valueSupplier
private static void printIfValidIndexSupplier(int number, Supplier<String> valueSupplier) {
if (number >= 0) {
System.out.println("The Supplier value is " + valueSupplier.get() + ".");
} else {
System.out.println("Invalid");
}
}
// 비교해보기 위해 일반 String value
private static void printIfValidIndex(int number, String value) {
if (number >= 0) {
System.out.println("The value is " + value + ".");
} else {
System.out.println("Invalid");
}
}
private static String getVeryExpensiveValue() {
try {
// 데이터를 가져오기 위해 2초가 걸린다고 가정...
TimeUnit.SECONDS.sleep(2);
} catch (Exception e) {
e.printStackTrace();
}
return "Expensive Value!!!";
}
위 함수는 문자열(무거운 데이터)을 얻기 위해 2초 가량 소모된다고 가정하자.
그리고 일반 String과 Supplier 를 통해 데이터를 가져오는 시간을 비교해보자.
long start = System.currentTimeMillis();
printIfValidIndex(0, getVeryExpensiveValue());
printIfValidIndex(-1, getVeryExpensiveValue());
printIfValidIndex(-2, getVeryExpensiveValue());
System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds");
System.out.println();
System.out.println();
long start2 = System.currentTimeMillis();
printIfValidIndexSupplier(0, SupplierExamples::getVeryExpensiveValue);
printIfValidIndexSupplier(-1, () -> getVeryExpensiveValue());
printIfValidIndexSupplier(-2, () -> getVeryExpensiveValue());
System.out.println("It took " + ((System.currentTimeMillis() - start2) / 1000) + " seconds");
//결과
The value is Expensive Value!!!.
Invalid
Invalid
It took 6 seconds
The Supplier value is Expensive Value!!!.
Invalid
Invalid
It took 2 seconds
https://codechacha.com/ko/java8-functional-interface/
https://www.youtube.com/watch?v=7e7FCMFrwcg&list=PLRIMoAKN8c6O8_VHOyBOhzBCeN7ShyJ27&index=7
https://bcp0109.tistory.com/313