목차
;5. Function의 합성과 Predicate의 결합
1. 람다식
1.1 람다식이란?
람다식 : 메서드를 하나의 식으로 표현한 것
메서드를 람다식으로 변형하면 메서드의 이름과 반환값이 없어지므로
"익명함수" 라고도 한다.
모든 메서드는 클래스의 포함되어야 하기에 클래스 제작 + 객체 생성이 필수적이지만
람다식은 다음의 과정이 없이 메서드 역할을 수행하게 할 수 있다.
1.2 람다식 작성하기
1) 메서드의 이름과 반환타입을 제거하고 ->을 블록 {} 앞에 추가한다
2) 반환값이 있는 경우 식이나 값만 적고 return 문 생략 가능(끝에 ;을 안붙임)
3) 매개변수 타입이 추론 가능하면 생략가능
*주의사항
- 매개변수가 하나일 때 => 괄호 생략가능(타입이 없을 때만)
- 불록 안의 문장이 하나뿐일 때 => 괄호() 생략 가능
- 단 하나뿐인 문장이 return 문이면 괄호{} 생략 불가
1.3 함수형 인터페이스
람다식은 익명 클래스 객체이다
그렇다면 그 익명 클래스 객체를 참조할 참조변수 타입은 무엇이어야 할까?
예를 들어 다음과 같은 interface가 있다고 가정해보자
inteface MyFunction(){
public abstract max(int a, int b);
}
여기서 이 인터페이스를 구현한 익명 클래스 객체는 다음과 같이 생성할 수 있다.
MyFunction f = new MyFunction(){
public int max(int a, int b) {
return a > b ? a : b;
}
};
그러나, 이 인터페이스는 람다식을 통해서도 구현이 가능하다.
람다식이 익명 클래스 객체이기 때문이다.
MyFunction f= (int a, int b) -> (a > b ? a : b);
int big = f.max(5,3);
이처럼 MyFunction 인터페이스를 구현한 익명 객체를 람다식으로 대체가능한 이유는
1) 람다식이 익명클래스 객체이다.
2) MyFunction 구현체인 익명 객체의 메서드 max() == 람다식의 max() 시그니처
이렇듯 하나의 메서드가 선언된 인터페이스는 람다식을 다루는데 있어 기존의 자바 규칙을 어기지 않으면서 자연스럽다. 따라서 람다식을 인터페이스를 통해 다루기로 하였으며, 이렇게 람다식을 다루기 위한 인터페이스를 [함수형 인터페이스]라고 부른다.
단, 함수형 인터페이스는 오직 하나의 추상메서드만 정의되어야 한다.
그래야 람다식과 인터페이스 메서드가 1:1로 대응되기 때문이다.
이것은 굉장히 큰 의의를 지닌다.
의미 : 함수형 인터페이스를 참조형으로 람다식을 참조변수처럼 다룬다.
== 메서드를 변수처럼 죽 받는 것이 가능해진다.
예를 들면 다음 함수형 인터페이스가 있다고 가정해보자
interface Comparator<T>{
int compare(T o1, T o2);
}
컬렉션을 sort할 때는 이 Comparator 인터페이스의 구현체가 들어가야 한다.
그럼 문자열 내림차순에 대해서는 다음처럼 생성할 수 있다.
그러나, 람다식을 사용하면 이 익명클래스 객체를 훨씬 간단히 마치 변수처럼 넣을 수 있다.
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
>> 람다식의 타입과 형변환
함수형 인터페이스로 람다식을 참조할 수 있는 것일 뿐,
함수형인터페이스 ==람다식이 아니다.
람다식은 익명 클래스의 객체이고, 익명 객체는 타입이 없다.
따라서 람다식은 생성 이후, 함수형 인터페이스로 형변환이 필요하다.
그러나, 이 형변환은 생략이 가능할 뿐이다.
MyFunction f = (MyFunction) (() ->{});
그렇다면 객체로의 형변환은 가능할까?
바로 객체 변환은 불가하고 함수형 인터페이스를 통해서 형변환은 가능하다.
[람다식 - 객체 변환]
람다식 -> 객체 (x)
람다식 -> 함수형 인터페이스 - > 객체 (o)
//잘못된 예시
Object obj = (Object) (() -> {} );
//옳은 예시
Object obj = (Object) (MyFunction) (() -> {} );
>> 람다식 주의 사항
1) 람다에서 참조하는 지역변수는 상수로 간주됨 => 값을 변경하면 오류 발생
2) 외부 지역변수와 같은 이름의 람다식 매개변수는 허용x
package ch14;
@FunctionalInterface
interface MyFunction{
void myMethod();
}
public class LambdaEx2 {
int val= 10;
void methid(int i){
int val=30;
// i=10; -> 에러1: 람다에서 사용한 지역변수는 상수로 취급
MyFunction f= (i)->{ //에러2. 외부 지역변수와 같은 이름을 사요하면 안되
System.out.println("i:"+i);
System.out.println("val : "+val);
System.out.println("this.val : " + this.val);
};
}
}
1.4 java.util.function패키지
java.util.function 패키지에는 일반적으로 자주쓰이는 형식의 메서드를 함수형 인터페이스로 미리 정의해놓았다.
매개변수가 2개인 함수형 인터페이스는 Bi를 붙이면 된다.
매개변수 자료형 == 반환형 자료형인 인터페이스는 다음과 같다.
UnaryOperator<T> -> 단항 연산자 ex) int increment(int x)
BinaryOperator<T> -> 이항 연산자 ex) int add(int a, int b)
함수형 인터페이스를 사용하는 컬렉션 프레임 워크도 알아보자
기본형을 사용하는 인터페이스도 존재한다.
AtoBFunction : A 타입을 매개변수로 받아 B 타입을 반한
AFunction : A타입을 매개변수로 받음
ObjAFunction : Obj와 A타입을 매개변수로 받음
ToBFunction : B타입을 반환
다만 IntToInt와 같이 매개변수와 반환형이 같은 인터페이스는 없다.
UnaryOperator가 그 역할을 해주고 있기 때문이다.
1.5 Function의 합성과 Predicate의 결합
요약
Function 합성
default <V> Function<T , V> andThen(Function ? super R, ? extends V) after) : f->g
default <V> Function<V, R> compose(Function ? super V, ? extends T) before) : g->f
static <T> Function <T,T> identity()
Predicate 결합
default Predicate<T> and(Predicate<? super T > other)
default Predicate<T> or(Predicate<? super T > other)
default Predicate<T> negate()
static <T> Predicate<T> isEqual(Object targetRef)
>>Function의 합성
수학에서 합성함수를 만들 수 있는 것처럼, 두 람다식을 합성해서 새로운 람다식을 만들 수 있다.
-andThen() : 순차적으로 결합 f->g
- compose : 수학의 합성함수 룰을 따름
- identity() : 함수를 적용하기 이전과 이후가 동일한 항등함수
Function<String, String> f = x->x;
Function<String, String > f = Function.identity();
>>Predicate의 결합
- and/or/negate : 조건식을 결합하는 것과 같은 맥락으로 사용
- isEqual() : 두 대상을 비교하는 조건식을 만들 때 사용
1.6 메서드 참조
람다식이 하나의 메서드만을 호출하는 경우, 메서드 참조를 통해 람다식을 더욱 간단히 할 수 있다.
여기서 메서드 참조는 `클래스 이름::메서드 이름` 혹은 `참조변수::메서드이름`의 형식을 가진다.
몇가지 사례를 통해 메서드 참조의 간편성을 알아보자
ex1) static 메서드를 참조한 사례
Integer method(String s){
return Integer.parseInt(s);
};
Function<String, Integer> f =(String s)-> Integer.parseInt(s);
Function<String, Integer> f2 = Integer::parseInt; //메서드 참조
ex2) new 연산자 : 메서드 참조
'기술 서적 > 자바의 정석' 카테고리의 다른 글
[자바의 정석] ch13. 쓰레드 (0) | 2024.02.11 |
---|---|
[자바의 정석] ch12. Generics / enums / annotation (0) | 2024.01.22 |
[자바의 정석] ch11-3.컬렉션 프레임워크 : HashMap/TreeMap / Collections (0) | 2024.01.20 |
[자바의 정석] 11-2.컬렉션 프레임워크 : iterator / Arrays / Comparator / Set (0) | 2024.01.16 |
[자바의 정석] ch11-1 : 컬렉션프레임워크 -- List / Stack-Queue (0) | 2024.01.14 |