본문 바로가기

프로그래밍/Java

[Java 요약 정리] 10. 람다식(Lambda Expression)

10. 람다(Lambda)


1) 람다식이란?

- 함수를 간단한 식(Expression)으로 표현하는 방법

- 익명함수(Anonymous function): 이름이 없는 함수

- 메소드는 클래스에 종속적이지만 함수는 클래스에 독립적


2) 람다식 작성하기

- 메소드의 이름과 반환타입을 제거하고 '->' 를 블록{} 앞에 추가

ex) int max(int a, int b) { return a > b ? a : b; } => (int a, int b) -> { return a > b ? a : b }

- 반환값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에 ; 안붙임)

ex) (int a, int b) -> { return a > b ? a : b } => (int a, int b) ->  a > b ? a : b

- 매개변수 타입이 추론 가능하면 생략 가능(대부분의 경우 생략 가능)

ex) (int a, int b) -> { a > b ? a : b } => (a, b) -> { a > b ? a : b }

- 매개변수가 하나인 경우 괄호() 생략 가능(타입이 없을 때만)

ex) (a) -> a*a => a -> a*a

- 블록 안의 문장이 하나뿐일 때 괄호{} 생략 가능(끝에 ; 안붙임)

(int i) -> {System.out.println(i);} => (int i) -> System.out.println(i)


3) 람다식 사용하기

함수형 인터페이스 타입의 참조변수로 람다식 참조 가능(매개변수, 반환타입 일치 필수)

ex)

Myfunction f = (a, b) -> a > b ? a : b;

int value = f.max(3,5)

* 함수형 인터페이스: 단 하나의 추상 메소드만 선언된 인터페이스


4) java.util.function패키지

- 자주 사용되는 함수형 인터페이스 제공


- 매개변수가 0 or 1개인 함수형 인터페이스

java.lang.Runnable // void run() => 매개변수 X 반환값 X

Supplier<T> // T get() => 매개변수X 반환값O

Consumer<T> // void accept(T t) => 매개변수O 반환값X

Function<T,R> // R apply(T t) => 매개변수O 반환값O

Predicate<T> // boolean test(T t) => 매개변수O 반환값Boolean


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

BiConsumer<T,U> // void accept(T t, U u) => 매개변수2, 반환값X

BiPredicate<T,U> // boolean test(T t, U u) => 매개변수2, 반환값boolean(조건식 표현에 사용)

BiFunction<T,U,R> // R apply(T t, U u) => 매개변수2, 반환값1


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

UnaryOperator<T> // T apply(T t) => Function의 자손, 타입 일치

BinaryOperator<T> // T apply(T t, T t) => BiFunction의 자손, 타입 일치


-함수형 인터페이스를 사용하는 컬렉션 프레임워크의 메소드

Collection // boolean removeIf(Predicate<E> filter) => 조건에 맞는 요소 삭제

List // replaceAll(UnaryOperator<E> operator) => 모든 요소를 변환해서 대체

Iterable // void forEach(Consumer<T> action) => 모든 요소에 작업 action을 수행

Map

V compute(K key, BiFunction<K,V,V> f) => 지정키값에 작업 f 수행

V computeIfAbsent(K key, Function<K,V> f) => 키가 없으면 작업 f 수행 후 추가

V computeIfPresent(K key, BiFunction<K,V,V> f) => 지정 키가 있을 때 작업 f 수행

V merge(K key, V value, BiFunction<V,V,V> f) => 모든 요소에 병합작업 f 수행

void forEach(BiConsumer<K,V> action) =>  모든 요소에 작업 action을 수행

void replaceAll(BiFunction<K,V,V> f) => 모든 요소에 치환작업 f를 수행


- 기본형을 사용하는 함수형 인터페이스

DoubleToIntFunction // int applyAsInt(double d) => A To B

ToIntFunction<T> // int applyAsInt(T value) => <지네릭> To B

IntFunction<R> // R apply(int value) => A To <지네릭>

ObjIntCunsumer<T> // void Accept(T t, int i) => T To 출력X


5) Function타입의 두 람다식을 하나로 합성

- andThen(): 참조변수a.andThen(참조변수b);

- compose(): 참조변수a.compose(참조변수b);

- and(), or(), negate(): 두 Predicate를 하나로 결합(default메소드)

- isEqual(): 등가비교를 위한 Predicate의 작성 (static 메소드)


6) 메소드 참조

- 하나의 메소드만 호출하는 람다식 간단히 줄임

- static메소드 참조 // (x) -> ClassName.method(x) => ClassName::method

- 인스턴스메소드 참조 // (obj, x) -> obj.method(x) => ClassName::method

- new연산자(생성자,배열)와 메소드 참조

Supplier<MyClass> s = MyClass::new;

Function<Integer, MyClass> f2 = MyClass::new;

Function<Integer, int[]> f2 = int[]::new;