본문 바로가기
개발 지식/Java

[Java] 함수형 인터페이스 @FunctionalInterface - 2. Consumer

by 에르주 2022. 3. 26.
반응형

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보다 크거나 같은 수");
}

실행 결과는 다음과 같다.

 

method 실행 결과

 

 

이번에는 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());
}

1consumer 예시

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 : 칼로리가 낮으니 조금만 더 먹어도 되는 피자");
});

 

 

lambda 형태

물론 예시코드에서 볼 수 있듯

 

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

 

 

반응형

댓글