Functional Interface : abstract method가 1개만 존재하는 Interface
사용할 때 Anonymous Class Object 생성 필요 없이 람다 expression으로 대체 가능.
(람다 expresstion의 타입이 Functional Interface 이기 때문에 가능함.)
Java 8 에서 총 4가지의 Functional Interface 가 추가됐음.
(Function, Comsumer, Predicate, Supplier)
* Function type
파라미터를 받아 특정 타입으로 리턴
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;}
}
identity : input 값과 return 값이 완전히 동일할 때 (타입, 내용 전부)
람다 없이 Anonymous Class를 사용한 경우
public classFunctionalInterfaceExample {
public static void main(String[] args) {
Function<String, Integer> toInt = new Function<String, Integer>() {
@Override
public Integer apply(final String value) {
return Integer.parseInt(value);
}
};
final Integer number = toInt.apply("100");
System.out.println(number);
}
}
Function 선언 시 Anonymous Cass Object를 사용해 코드가 아주 길어졌다.
람다 Expression 사용시
public classFunctionalInterfaceExample {
public static void main(String[] args) {
final Function<String, Integer> toInt = value -> Integer.parseInt(value);
final Integer number = toInt.apply("100");
System.out.println(number);
}
}
<identity>
final Function<Integer, Integer> identity = Function.identity();
// Function 클래스 안에 static 메서드 identity() 는 람다 메서드를 반환 (t -> t)
// 그래서 위처럼 사용 가능
* Consumer
파라미터를 받아 아무것도 리턴하지 않음
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.accrpt(t); };
}
}
람다 없이 Anonymous Class를 사용한 경우
final Consumer<String> print = new Consumer<String>() {
@Override
public void accept(final String value) {
System.out.println(value);
};
print.accept("Hello");
람다 expression을 사용한 경우
final Consumer<String> print = value -> System.out.print("value");
print.accept("Hello");
*Predicate
결괏값이 항상 boolean인 Functional Interface.
Function <T, Boolean>과 역할은 같음. 추가적인 기능이 있어서 Predicate로 분리했을까?
public interface Predicate<T> {
boolean teest(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);
}
static <T> Predicate<T> not(Predicate<? super T> target) {
Objects.requireNonNull(target);
return (Predicate<T>)target.negate();
}
}
Predicate<Integer> isPositive = value -> value > 0;
System.out.println(isPositive.test(1));
*Supplyer
Lazy evaluation 가능!
public interface Supplier<T> {
T get();
}
final Supplier<String> helloSupplier = () -> "Hello ";
System.out.println(helloSupplier.get() + "world");
이런 사용법이면 왜 Supplyer Function Interface를 사용할까? 그냥 Hello를 넣으면 될 텐데
바로 Lazy evaluation을 위해!
private String getVeryExpensiveValue() {
try {
TimeUnit.SECONDS.sleep(3);
}catch (InterruptedException e) {
e.printStackTrace();
}
return "Value";
} // 이 메서드는 매우 많은 시간이 걸려 값을 반환한다 가정! (sleep으로 강제 가정)
---
private static void printIfValidIndex1(int num, String value) {
if(num >= 0) {
System.out.println("The value is " + value + ".");
}else {
System.out.println("Invalid");
}
}
printIfValidIndex(0, getVeryExpensiveValue());
printIfValidIndex(-1, getVeryExpensiveValue());
printIfValidIndex(-2, getVeryExpensiveValue());
// -1, -2 일 땐 getVeryExpensiveValue 실행 필요 없지만, 전체 프로그래밍 시간은 9초로 계산을 진행함
---
private static void printIfValidIndex2(int num, Supplier<String> valueSupplier) {
if(num >= 0) {
System.out.println("The value is " + valueSupplier.get() + ".");
}else {
System.out.println("Invalid");
}
}
printIfValidIndex(0, () -> getVeryExpensiveValue());
printIfValidIndex(-1, () -> getVeryExpensiveValue());
printIfValidIndex(-2, () -> getVeryExpensiveValue());
// 0 일때만 getVeryExpensiveValue 가 실행되 총 3초만 소요'코딩 > JAVA 공부' 카테고리의 다른 글
| 논리 연산자 &, |와 &&, ||의 차이 (0) | 2023.04.07 |
|---|---|
| [JAVA] String 문자열 더하기 (0) | 2023.04.04 |
| [객체지향] 의존성을 이용해 설계 진화시키기 (0) | 2022.12.03 |
| [JAVA] 자바의 정석 _ 스트림(Stream) (0) | 2022.10.29 |
| [JAVA] 자바의 정석 _ Optional<T> (0) | 2022.10.28 |