자바8 함수형 인터페이스
인터페이스명 | 메서드명 | 내용 |
Consumer<T> | void accept(T t) | 파라미터를 전달해서 처리한 후 결과를 리턴 받을 필요가 있을 때 사용한다. 받기만 하고 리턴은 없다. 그러므로 Consumer라는 이름을 사용. 예) 메일보내기, 리포트, 어떤 동작을 수행 후 결과를 받아야 하는 기능에 이용 |
Function<T , R> | R applay(T t) | 전달할 파라미터를 다른 값으로 변환해서 리턴할 때 사용한다. 주로 값을 변경하거나 매핑할때 사용한다. 예) 1,000,000만원의 10% 이자를 구한다거나, 어떤 값을 넣었을 때 대응하는 값을 리턴하거나 할때 |
Predicate<T> | boolean test(T t) | 전달받은 값에 대해 true/false 값을 리턴할 때 사용. 주로 데이터를 필터링하거나, 조건에 맞는지 여부를 확인하는 용도로 사용한다. |
Supplier<T> | T get() | 파라미터 없이 리턴 값만 있는 경우 사용한다. 인수를 받지는 않고 리턴만 하기 때문에 Supplier라는 이름을 사용한다. |
자바8이 나온 지도 꽤 됐지만 의외로 자바 8의 이점을 사용하지 못하곤 한다.
함수형인터페이스는 리액티브 프로그래밍과 결합되었을 때 비로소 명확하고 많은 이점이 생기지만 리액티브의 러닝커브는 상당히 가파르다는 단점 아닌 단점이 있는 게 사실이다.
그래도 반복하고 훈련을 하다보면 함수형 프로그래밍에 익숙해지게 된다.
점점 세상은 복잡해지고, 어플리케이션도 분산시스템화되어 패러다임이 바뀌고 있다.
자바8 이전의 코딩 방식으로도 충분할 수도 있고 아닐 수도 있다.
1. Consumer 인터페이스
Consumer 인터페이스는 이름 그대로 소비한다. 소비한다는 의미는 어떤 값도 리턴하지 않고 요청받은 내용을 처리한다는 것이다. 그러므로 void 다.
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class ConsumerExample {
public static void executeConsumer(List<String> workList, Consumer<String> consumer){
for(String work : workList){
consumer.accept(work);
}
}
public static void main(String[] args) {
List<String> workList = new ArrayList<>();
workList.add("서울 지역의 매출을 집계한다.");
workList.add("부산 지역의 매출을 집계한다.");
workList.add("서울과 부산 지점에 메일을 보낸다");
ConsumerExample.executeConsumer(workList, work -> {
System.out.println(work);
});
}
}
ConsumerExample.java 결과
2. FunctionalExample 인터페이스
두 번째는 Function 인터페이스다.
T를 인수로 받아 R로 리턴하는 apply메서드를 갖고있다.
어렵게 생각할 필요는 없다.
단순한 예제로 1,000원의 10%를 구하는 기능을 구현해 본다.
import java.util.function.Function;
public class FunctionExample {
public static double exeDoubleFunction(double manageAmt, Function<Double, Double> function){
return function.apply(manageAmt);
}
public static void main(String[] args) {
double result = FunctionExample01.exeDoubleFunction(10000, amt -> {
double result01 = amt * 0.1;
return result01;
});
System.out.println("10,000원의 10%는 : " + result);
}
}
FunctionExample.java 결과
주로 데이터를 가공하거나 매핑하는 용도로 많이 사용하며, 비즈니스 로직에 대한 리턴 값이 필요할 경우, 어떤 계산값을 구할 때 사용하면 아주 유용하다. 미납요금의 연체료, 지체상금등이 그런 예이다.
3. Predicate 인터페이스
어떤 기능을 처리 후에 성공 혹은 실패했는지를 확인하고 싶은 경우나 값에 대한 검증을 수행하는 등의 작업을 처리할 때 사용한다.
예) name 값이 비어있는지 체크하는 밸리데이션 메서드로 활용한 예.
import java.util.function.Predicate;
public class PredicateExample {
public static boolean isValid(String name, Predicate<String> predicate){
return predicate.test(name);
}
public static void main(String[] args) {
boolean isValid = PredicateExample.isValid("",name->!name.isEmpty());
System.out.println(isValid);
}
}
4. Supplier인터페이스
파라미터/인자 값 없이 리턴 타입만 있는 메서드로 주로 지정된 정보를 확인하거나 조회할 때 유용하게 사용할 수 있다.
import java.util.function.Supplier;
public class SupplierExample {
public static String executeSupplier(Supplier<String> supplier){
return supplier.get();
}
public static void main(String[] args) {
System.out.println(
SupplierExample.executeSupplier(() -> {
System.out.println("DataBase에서 자료를 가져옴");
return "부산 지역 100개 매장의 매출 리스트를 리턴";
}));
}
}
위에 기술한 간단한 예제들을 어떻게 복잡한 애플리케이션을 만드는 적소에 사용할지 망막하겠지만, Git이나 스프링 WebFlux 등의 예제를 참고하고 연습하면 자연스럽게 막강한 함수형 프로그래밍의 매력에 빠지게 된다.
RxJava의 백프레셔 예제.
import com.spr.reactivexo.rxjava.CommonUtils;
import com.spr.reactivexo.rxjava.Log;
import io.reactivex.rxjava3.schedulers.Schedulers;
import io.reactivex.rxjava3.subjects.PublishSubject;
public class BackPressure01 {
public static void main(String[] args) {
CommonUtils.exampleStart();
PublishSubject<Integer> subject = PublishSubject.create();
subject.observeOn(Schedulers.computation())
.subscribe(data -> {
CommonUtils.sleep(1000);
Log.it(data);
} , err -> Log.e(err.toString()));
// Hot Observable 로 50,000,000 개의 데이터를 연속으로 발행함.
for(int i =0 ; i < 50_000_000 ; i++){
subject.onNext(i);
}
subject.onComplete();
}
}
'슬기로운 자바 개발자 생활 > 모던 자바와 Reactive' 카테고리의 다른 글
인텔리J에서 Reactivex RX Java 시작하기 (0) | 2023.02.11 |
---|---|
자바8 람다. 메서드 전달 (0) | 2023.01.25 |
네티 Netty 프레임워크 공부 02 양방향 통신 (예제 첨부) (0) | 2022.12.21 |
네티 Netty 프레임워크 공부 01 (예제 첨부) (0) | 2022.12.21 |
댓글