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

Pongchi·2022년 12월 19일

Java의 정석

목록 보기
6/6
post-thumbnail

람다식(Lambda Expression)

정의

  • 함수형 언어 기능이다.
  • 함수(메서드)를 간단한 식(expression)으로 표현하는 것
  • 익명 함수이다.

람다식 작성 방법

  1. 메서드의 이름과 반환타입을 제거하고 -> 를 블록{} 앞에 추가한다.
// 수정 전
int max(int a, int b) {
	return a > b ? a : b;
}

// 수정 후
(int a, int b) -> { return a > b ? a : b; }
  1. 반환값이 있는 경우, 식이나 값만 적고 return 문 생략 가능.
    끝에 ;(세미콜론) 안붙임
(int a, int b) -> a > b ? a : b
  1. 매개변수의 타입이 추론 가능하면 생략가능. (대부분의 경우 생략가능)
(a, b) -> a > b ? a : b

람다식 작성 주의사항

  1. 매개변수가 하나인 경우, 괄호 생략가능 (타입이 없을 때만)
// 수정 전
(a) -> { a * a }

// 수정 후
a -> { a * a }

// 에러 사항
int a -> { a * a }	// 타입이 있어서 에러가 뜸
  1. 블록 안의 문장이 하나뿐 일 때, 괄호 생략 가능 (끝에 ;(세미콜론) 안 붙임)
a -> a * a
  1. 문장이 하나 뿐일 때, return문이면 괄호 생략 불가
(a, b) -> return a > b ? a : b	// Error

람다식 사용방법

  • 람다식은 익명 함수가 아니라 익명 객체이다.
  • 람다식을 다루기 위한 참조변수가 필요하다.
  • 하지만, 결국 익명이지만 호출할려고 이름을 붙여야 한다.
  • 그걸 함수형 인터페이스를 통해 한다.

함수형 인터페이스(Functional Interface)

정의

단 하나의 추상 메서드만 선언된 인터페이스

사용방법

@FunctionalInterface
interface MyFunction {
	public abstract int max(int a, int b);
}

public class Main {
	public static void main(String[] args) {
    	MyFunction f = new MyFunction() {
        	public int max(int a, int b) {
            	return a > b ? a : b;
            }
        }
       
        System.out.println( f.max(3, 5) ); 	// 5
       
    }
}

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

함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있다.
단, 함수형 인터페이스의 메서드와 람다식의 매개변수 개수와 반환 타입이 일치해야 한다.

예시

MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3, 5);	// 실제로 람다식이 호출됨

익명 객체와 람다식

  • Comparator를 사용할 때, 따로 익명 객체를 사용하는데 코드 문법이 길다.
  • 하지만 람다식을 이용해 대폭 줄일 수 있음
// 수정 전
List<String> list = Arrays.asList("a", "b", "c", "d");
Collections.sort(list, new Comparator<String>() {
							public int compare(String s1, String s2) {
                            	return s2.compareTo(s1);
                            }
                        });

// 수정 후
List<String> list = Arrays.asList("a", "b", "c", "d");
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));

java.util.function 패키지

자주 사용되는 다양한 함수형 인터페이스를 제공

기본

  • Supplier<T> : T get()
  • Consumer<T> : void accept(T t)
  • Function<T, R> : R apply(T t)
  • Predicate<T> : boolean test(T t)

매개변수가 2개인 함수형 인터페이스

  • BiConsumer<T, U> : void accept(T t, U u)
  • BiPredicate<T, U> : boolean test(T t, U u)
  • BiFunction<T, U, R> : R apply(T t, U u)

매개변수의 타입과 반환타입이 일치하는 함수형 인터페이스

  • UnaryOperator<T> : T apply(T t)
  • BinaryOperator<T> : T apply(T t, T t)

메서드 참조(method reference)

하나의 메서드만 호출하는 람다식은 '메서드 참조'로 간단히 할 수 있음

기본

  • static 메서드 참조
  • 인스턴스메서드 참조
  • 특정 객체 인스턴스메서드 참조 ( 이건 거의 안씀 )

사용법과 예시

// 사용법 : 클래스이름::메서드이름
Integer method(String s) {
	return Integer.parseInt(s);
}

Function<String, Integer> f = (String s) -> Integer.parseInt(s); // 원래 람다식
Function<String, Integer> f = Integer::parseInt;				 // 메서드 참조

생성자의 메서드 참조

Supplier<MyClass> s = () -> new MyClass(); 		// 원래 람다식
Supplier<MyClass> s = MyClass::new;				// 메서드 참조

Function<Integer, MyClass> s = (i) -> new MyClass(i);	// 원래 람다식
Function<Integer, MyClass> s = MyClass::new;			// 메서드 참조

// 배열
Function<Integer, int[]> f = x -> new int[x];		// 원래 람다식
Function<Integer, int[]> f = int[]::new;			// 메서드 참조
profile
- I'm going to be a ???

0개의 댓글