[Java] 람다식과 함수형 인터페이스

KKS·2024년 2월 8일
0

Java

목록 보기
6/6
post-thumbnail

개요

본 포스팅의 목적

  • 람다식을 처음 접했을 때, 굉장히 익숙치 않아서 친해지기까지 꽤 오랜 시간이 걸렸다.
  • 람다식을 이해하기 위해서는 메서드는 기본이고, 내부 클래스와 익명 객체, 함수형 인터페이스의 이해가 필수적이다.
  • 이러한 복합적인 개념들이 한 데 모여 간소화한 것이 람다식의 형태인데, 자바 초보자의 입장에서 람다식을 처음 보면 매우 낯설게 느껴진다.
  • 따라서, 본 포스팅에서는 예제와 모식도를 활용하여 낯선 람다식과 함수형 인터페이스를 친숙하게 느껴보고자 한다.

람다식을 한마디로 표현하면 ?

  • 람다식을 한마디로 표현하기란 여간 쉬운 일이 아닌 것 같다.
  • 람다식을 빈틈없이 한 마디로 표현해볼 수 있는 문장을 생각해보았는데, 내 기준에서는 아래와 같은 문장이 가장 적합한 것 같다.

"람다식이란, 함수형 인터페이스를 구현한, 메서드처럼 생긴(?) 익명 객체이다."

  • 위의 개념을 이해하기 위해 함수형 인터페이스, 익명객체, 람다식을 코드로 표현하면 다음과 같다.
//1. 함수형 인터페이스
@FunctionalInterface
interface MyFunction {
	//단 하나의 추상메서드
	public abstract int max(int a, int b);
}

//2. 익명객체 : 함수형 인터페이스의 추상메서드를 구현, 참조변수의 타입은 함수형 인터페이스
MyFunction myFunction = new MyFunction() {
	public int max(int a, int b) {
		return a > b ? a : b;
	}
};

//3. 람다식 : 위의 익명객체를 간단히 표현할 뿐, 익명객체와 동일하다.
MyFunction myFunction = (a, b) -> a > b ? a : b;

//4. 람다식 호출 : 람다식의 메서드는 이름이 없으므로, 구현한 함수형 인터페이스의 메서드 이름을 사용한다.
int bigNum = myFunction.max(5, 10); //bigNum=10

함수형 인터페이스의 유형

  • 함수형 인터페이스는 단 하나의 추상메서드를 지닌다. (static메서드, default메서드 제외)
  • 이 함수형 인터페이스로 람다식을 참조할 수 있다. 람다식을 참조할 수 있다는 것은, 람다식의 메서드를 호출할 수 있다는 것이다. 대표적으로 get, accept, apply, test메서드가 있다.
  • 자바에서는 java.util.function패키지에 메서드의 반환타입매개변수에 따라 자주 사용되는 함수형 인터페이스와 메서드를 아래와 같이 정의해놓았다.

람다식과 함수형 인터페이스 사용 예제

  • java.util.function패키지에 정의된 각각의 함수형 인터페이스의 내부 코드를 살펴보고, 간단한 사용 예제를 보자.

1. Supplier < T >

//함수형 인터페이스 Supplier
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

//사용 예시
Supplier<Integer> sup = () -> (int)(Math.random()*100 + 1);
int random = sup.get(); //난수

2. Consumer < T >

//함수형 인터페이스 Consumer
@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

//사용 예시
Consumer<Integer> con = (i) -> System.out.println(i);
c.accept(1234); //1234

3. Function < T, R >

//함수형 인터페이스 Function
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}

//사용 예시
Function<Integer, Integer> func = (i) -> (i/10)*10;
int num = func.apply(15); // num=10

4. Predicate < T >

//함수형 인터페이스 Predicate
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

//사용 예시
Predicate<Integer> pre = (i) -> i % 2 == 0;
boolean isEven = pre.test(15); //isEven=false

결론

  • 위에서 살펴본 것 외에도 다양한 함수형 인터페이스가 존재하지만, 메서드는 대개 반환타입이 없거나 1개, 매개변수 역시 많아봤자 2~3개 이므로 형태가 고정되어 있다고 볼 수 있다.
  • 람다식과 함수형 인터페이스를 제대로 이해하고 사용할 줄 알아야 추후 스트림을 배우는 데에도 어려움이 없을 것이다.
  • 나같은 초보자들은 기존에 배웠던 기본적인 메서드를 사용하면 굳이 어려운 람다식을 배우지 않아도 좋을텐데.. 라고 생각할 수도 있겠지만, 람다식이 점차 익숙해지면서 기존 코드보다 간략하고 명료함을 체감하고 함수형 프로그래밍과 조금 더 친해질 수 있는 계기가 되었으면 좋겠다.

참고서적

  • 자바의 정석(남궁성 저)
profile
공부하고 이해한 내용들을 직접 그림과 표를 그리면서 정리해보는 공간입니다.🤗

1개의 댓글

comment-user-thumbnail
2024년 2월 15일

항상 응원합니다요~

답글 달기