스트림에서 사용되는 함수형 인터페이스

Choizz·2023년 1월 17일
0

Java

목록 보기
2/11
post-thumbnail

자바에서 Collection 타입을 사용하다 보면 자연스럽게 스트림과 람다식을 사용하게 된다.

stream의 map 메서드와 filter 메서드, forEach 메서드에 사용된 람다식은 모두 같지만 map에서는 컴파일에러가 나지 않고, 나머지 메서드에서는 컴파일 에러가 난다.

이것은 스트림 람다식이 각 메서드에 알맞은 방식으로 작성돼야 한다는 것을 의미한다.

위 이미지에 사용된 메서드들을 자세히 알아보면 각각 괄호 안에 받는 것이 각각 다 다르다는 것을 알 수 있다.

Stream<T> filter(Predicate<? super T> predicate); //Predicate

<R> Stream<R> map(Function<? super T, ? extends R> mapper); //Function

void forEach(Consumer<? super T> action); //Consumer

즉, 메서드에 함수형 인터페이스가 제공하는 타겟 타입에 맞추어 람다식을 사용해야 하는 것이다.

오늘은 이렇게 스트림 메서드에 사용되는 함수형 인터페이스에 대해 알아보자!


함수형 인터페이스

함수형 인터페이스에 대해 알아보면,

하나의 추상 메서드의 선언을 포함한 인터페이스

를 의미한다. 이것은, 추상 메서드가 없거나 추상 메서드 선언을 2개 이상 가진 인터페이스는 함수형 인터페이스가 아니라는 것을 말한다. (default 메서드나 static 메서드는 제외)

함수형 인터페이스는 @FunctionalInterface 애노테이션을 붙여 선언한다.

Java 8에서는 Java.util.function 패키지에 많은 함수형 인터페이스가 존재하지만 이 호스팅에서는 중요한 몇 가지를 알아볼 것이다.

1. Supplier 인터페이스

Supplier는 공급자라는 의미대로 인수없이 리턴 값을 반환하는 추상 메서드를 가지고 있다.

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
  • 어떤 인자도 받지 않고 반환하기만 하는 람다식 표현을 사용하면 된다.
Optional<User> optionalUser = userRepository.findByDisplayName(displayName);
optionalUser.orElseThrow(() -> new RuntimeException("테스트"));

2. Consumer 인터페이스

Consumer는 어떠한 인자를 받으나 리턴 값은 없는 추상 메서드를 가지고 있다.

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    //생략
}
  • 타입이 없는 void 메서드를 사용한다고 생각하면 이해가 쉽다. 물론 리턴 타입이 있는 메서드를 사용해도 에러가 발생하지는 않는다. 다만 리턴 값이 없을 뿐이다.
testLists.forEach(m -> System.out.println(m));

3. Predicate 인터페이스

Predicate 인터페이스는 인자를 평가하는 추상 메서드를 가지고 있다. 인수로 받은 것에 대해 조건에 맞으면 true, 틀리면 false를 리턴한다.

@FunctionalInterface
public interface Predicate<T> {
    boolean test(T t);

    //생략
}
  • filter 메서드는 타겟 타입이 Predicate로 조건에 따라 true인 stream을 리턴한다.
 List<Integer> testLists = List.of(1, 2, 3, 4, 5);

 Predicate<Integer> integerPredicate = n -> n % 2 == 0;
 testLists.stream().filter(integerPredicate).forEach(System.out::println);

4. Function 인터페이스

Function 인터페이스는 받은 인수(T)를 가공하여 결과로 다른 리턴 값(R)을 리턴하는 추상 메서드를 가지고 있다.

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    //생략
}
  • 아래 식에서 map 메서드는 인자들을 받아 2를 곱한 값을 스트림으로 리턴한다.
List<Integer> testLists = List.of(1, 2, 3, 4, 5);

testLists.stream().map(n -> n * 2);

정리

지금까지 대표적인 함수형 인터페이스에 대해서 알아봤다. 이 외에도 많은 함수형 인터페이스들이 존재하지만 나머지는 파생되는 개념이라 필요할 때 공부해보면 될 것이라고 생각한다.
참고: java.util.fucntion


Reference

profile
집중

0개의 댓글