2022.03.11 - [개발 지식/Java] - [Java] 함수형 인터페이스 @FunctionalInterface - 1. Predicate
[Java] 함수형 인터페이스 @FunctionalInterface - 1. Predicate
개발을 진행하다보면 람다 표현식을 많이 쓰게 된다. 특히 Stream API를 활용할 때 자주 쓰게 된다. 관련된 서적이나 구글에서 보면 "함수형 인터페이스를 람다 표현식을 사용할 수 있다" 라고 하는
erjuer.tistory.com
이번에는
2. Consumer
함수형 인터페이스를 한꺼번에 정리하고자 한다.
2. Consumer
Comsumer는 말 그대로 소비자라는 말과 같이 Return값을 내 뱉는 것이 아닌 void를 반환하는 추상 메소드 (accept) 를 정의한다.
(지난번 Predicate와 마찬가지로 accept는 추상 메소드이므로 "accept"라는 메소드명에 초점을 맞추는 것이 아닌 단순히 "void를 반환하는 메소드다" 라고 이해하는 것이 옳다.)
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
* // 전달 받은 매개변수로 수행된다.
* @param t the input argument
* // 파라미터 t는 입력 매개변수이다.
*/
void accept(T t);
}
//////////////////////////////////////////////
public <T> void somethingOperation(T t) {
}
// accept와 somethingOperation 함수의 로직은 같다.
이번에 코드로 들어 볼 예시는 Integer List를 가지고 10보다 크다 작다 여부를 판별하는 메소드이다.
Consumer 객체를 이용하기 전 로직을 단순 메소드로 활용하여 나타내면 다음과 같을 것 이다.
// List를 매개변수로 받아 출력하는 메소드
public <T> void forEachByMethod(List<T> list) {
for(T t: list){
printNumberSize((Integer) t);
}
}
// 주어진 Integer값에 따른 분기 처리
public void printNumberSize(Integer num) {
if(num < 10) System.out.println(num + ": 10보다 작은 수");
else System.out.println(num + ": 10보다 크거나 같은 수");
}
실행 결과는 다음과 같다.

이번에는 Consumer 객체를 이용해보자.
// 10보다 큰지 작은지 Print 해주는 method (Consumer 객체)
public <T> Consumer<T> consumerEx() {
return new Consumer<T>() {
@Override
public void accept(T t) {
if((Integer) t < 10) System.out.println(t + ": 10보다 작은 수");
else System.out.println(t + ": 10보다 크거나 같은 수");
}
};
}
// consumer 객체를 받아 처리하는 method
public <T> void forEachByConsumer(List<T> list, Consumer<T> consumer) {
for(T t: list){
consumer.accept(t);
}
}
// 실행 Method
public void consumerMethod(){
List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 10, 11, 12, 13, 14);
forEachByConsumer(integerList, consumerEx());
}

1. consumerEx
consumerEx 메소드는 consumer 객체를 리턴한다. 즉 consumer 추상 메소드(accept)를 @Override 하여 구체화 한다.
이번 예제에서는 추상메소드 즉 accpt 메소드를 Intege값에 따른 println으로 정의하였다.
2. forEachByConsumer
List 객체와 Consumer 객체를 매개변수로 받는다. List 객체에 consumer accept 객체를 적용한다. 이 함수의 매개변수 Consumer 객체는 consumerEx()에서 정의한 객체이다.
물론 해당 Consumer 또한 lambda 표현식을 이용해서 나타 낼 수 도 있다.
public <T> Consumer<T> consumerLambdaEx() {
return t -> {
if((Integer) t < 10) System.out.println(t + ": 10보다 작은 수");
else System.out.println(t + ": 10보다 크거나 같은 수");
};
}
또 다른 예시를 들어보자.
이번에 코드로 들어 볼 예시는 Pizza 객체 List를 가지고칼로리별 sout을 하는 메소드이다.
/* Pizza 클래스 */
public class Pizza extends Eat implements Serializable {
int kcal; // 칼로리
String kindValue; // 음식 종류 (피자)
public Pizza(int kcal, String kindValue) {
super(kcal,kindValue);
this.kcal =kcal;
this.kindValue = kindValue;
}
}
/* consumer 클래스 */
// Pizza 칼로리에 따라 if 분기 처리
public <T> Consumer<T> pizzaConsumerEx() {
return new Consumer<T>() {
@Override
public void accept(T t) {
Pizza pizza = (Pizza) t;
if(pizza.getPizzaKcal() > 500) System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 맛있으니 조금만 더 먹어도 되는 피자");
else System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 칼로리가 낮으니 조금만 더 먹어도 되는 피자");
}
};
}
public void consumerMethod(){
List<Pizza> pizzaList = Arrays.asList(new Pizza(300, "콤비네이션 피자"), new Pizza(250,"야채 피자"), new Pizza(600,"치즈 피자"), new Pizza(550, "고구마 피자"));
forEachByConsumer(pizzaList, pizzaConsumerEx());
}

또 Consumer 객체를 람다 표현식으로 나타 내면 다음과 같다.
public <T> Consumer<T> pizzaConsumerLambdaEx() {
return t -> {
Pizza pizza = (Pizza) t;
if(pizza.getPizzaKcal() > 500) System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 맛있으니 조금만 더 먹어도 되는 피자");
else System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 칼로리가 낮으니 조금만 더 먹어도 되는 피자");
};
}
Consumer 객체는 Java Stream에서도 활용 할 수 있다.
Stream의
- forEach
- forEachOrder
- peek
- sort
4개의 메소드에서 활용할 수 있다.
// integerlist consumer accept 메소드 적용
integerList.stream().forEach(consumerEx());
System.out.println("=======================");
// pizzaList consumer accept 메소드 적용
pizzaList.stream().forEach(pizza -> {
if(pizza.getPizzaKcal() > 500) System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 맛있으니 조금만 더 먹어도 되는 피자");
else System.out.println(pizza.getPizzaValue() + ", "+ pizza.getPizzaKcal() + "kcal : 칼로리가 낮으니 조금만 더 먹어도 되는 피자");
});

물론 예시코드에서 볼 수 있듯
1. Consumer<T> 객체를 리턴하는 메소드를 활용
2. Lambda 표현식 활용
두가지 방법을 모두 활용할 수 있다.
끝.
예시 코드는 다음 repo에 있다.
https://github.com/pminsu01/JavaStudy
GitHub - pminsu01/JavaStudy: 자바 자체 스터디
자바 자체 스터디. Contribute to pminsu01/JavaStudy development by creating an account on GitHub.
github.com
'개발 지식 > Java' 카테고리의 다른 글
[Java] 함수형 인터페이스 @FunctionalInterface - 3. Function (0) | 2022.04.13 |
---|---|
[Java] The server selected protocol version TLS10 is not accepted by client preferences [TLS13, TLS12] (0) | 2022.03.28 |
[Java] 함수형 인터페이스 @FunctionalInterface - 1. Predicate (0) | 2022.03.11 |
[Java] 제네릭(Generic)이 무엇일까 그리고 활용법 (0) | 2022.01.09 |
[Optional] orElse와 orElseGet의 차이 (0) | 2021.12.30 |
댓글