Lambda Expression
람다의 특징 (Java 1.8이상)
1. 익명
보통의 메소드와 달리 이름이 없다.
2. 함수
특정 클래스에 종속되지 않아 함수라 부른다.
3. 전달
람다 표현식을 메서드의 인자로 전달하거나 변수로 저장할 수 있다.
4. 간결성
익명 클래스처럼 자질구레한 코드를 구현할 필요가 없다.
익명클래스 (Java 1.8미만)
코드가 지저분해지는 단점
예시)
public static void main(String[] args) {
Main main = new Main();
// fp_java.ch01.anonymousclass.Main@1f32e575
System.out.println(main);
// fp_java.ch01.anonymousclass.Main$SubMain@2ff4acd0
// 이름이 있기 때문에 $+이름
SubMain submain = new SubMain();
System.out.println(submain);
// 인터페이스에 있던 메소드 구현 -> 이름없는 클래스, 익명클래스 구현
Computable computer = new Computable() {
@Override
public int add(int num1, int num2) {
return num1 + num2;
}
};
// fp_java.ch01.anonymousclass.Main$1@27716f4
// 이름이 없기 때문에 $1
System.out.println(computer);
Computable computer2 = new Computable() {
@Override
public int add(int num1, int num2) {
return num1 + num2;
}
};
// fp_java.ch01.anonymousclass.Main$2@2a84aee7
// 이름이 없기 때문에 $2
System.out.println(computer2);
람다의 적용
람다의 구성
람다 파라미터
Compartor의 compare 메소드의 파라미터 (두 명의 사원)
파라미터가 1개라면 괄호 생략 가능
파라미터가 없다면 빈 괄호 () 만
화살표 ( -> )
람다의 파라미터 리스트와 바디를 구분함.
람다 바디
두 명의 사원 번호를 구분함. 람다의 반환값에 해당하는 표현식
중괄호가 없으면 반환을 시키지 않을 거란 뜻도 가능
여러줄을 쓸 때 중괄호 필수
Java 8에서 유효한 다섯가지 람다 표현식
{} 중괄호가 있는 람다 표현식에서 리턴이 필요한 경우
return을 명시적으로 작성해야 한다.
람다는 반드시 하나의 추상메소드만 존재해야 한다.
위처럼 이렇게 두가지가 안된다는 뜻
이것을 해결하는 방법은 public void printMessage();을 인터페이스에 메소드로 구현
인터페이스에 메소드 구현 1.8부터 가능
예시)
package fp_java.ch01.lambda;
@FunctionalInterface
public interface Computable {
public int add(int num1, int num2);
/**
* 인터페이스의 printMessage 기본 코드를 작성
* default 키워드를 가장 앞에 붙이면
* 인터페이스도 기능을 구현할 수 있다.
* implementable class 에서 overriding 가능하다.
* overriding 해주지 않으면 기본코드가 동작된다.
*/
default public void printMessage() {
System.out.println("기본 메세지입니다.");
}
}
위에서 만들어주면
// 람다 (정석)
Computable lambdaComputer = (int num1, int num2) -> num1 + num2;
int lambdaResult = lambdaComputer.add(10, 20);
System.out.println(lambdaResult);
lambdaComputer.printMessage();
// 람다 (실무)
Computable lambdaComputer2 = (num1, num2) -> num1 + num2;
int lambdaResult2 = lambdaComputer2.add(30, 10);
System.out.println(lambdaResult2);
lambdaComputer2.printMessage();
이렇게 lambdaComputer.printMessage(); 간편한 방법으로 다른 클래스에서 사용 가능하다.
함수형 인터페이스
- 람다는 함수형 인터페이스를 파라미터로 받는 메소드에게만 사용할 수 있다.
- 함수형 인터페이스는 오직 하나의 추상메소드만 지정되어 있는 인터페이스를 말한다.
- Comparator 인터페이스의 추상메소드는 int compare(T o1, T 02); 하나.
함수형 인터페이스의 종류
Predicate<T>
: 파라미터 하나를 전달받아, boolean을 반환하는 함수형 인터페이스
BiPredicate<L, R>
: 파라미터 L과 R을 전달받아 boolean을 반환하는 함수형 인터페이스
Consumer<T>
: 파라미터 하나를 전달받아, void를 반환하는 함수형 인터페이스 // void 아무것도 반환 x
BiConsumer<T, U>
파라미터 T와 U를 전달받아 void를 반환하는 함수형 인터페이스 // void 아무것도 반환 x
Function<T, R>
: 파라미터 T를 전달받아 R을 반환하는 함수형 인터페이스
BiFunction<T, U, R>
: 파라미터 T와 U를 전달받아( funtion에서만 R이 리턴) R 을 반환하는 함수형 인터페이스
예시)
package fp_java.ch01.lambda;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
public class BuiltInFunctionalInterface {
public static void main(String[] args) {
// 익명클래스
Predicate<Integer> pp = new Predicate<Integer>() {
@Override
public boolean test(Integer t) {
return t >= 19;
}
};
boolean isAdult = pp.test(20);
System.out.println(isAdult);
// 람다
Predicate<Integer> p = (t) -> t >= 19;
boolean isAdult2 = p.test(15);
System.out.println(isAdult2);
Consumer<String> c = t -> System.out.println(t); // 파라미터 1개일때는 () 생략가능
c.accept("반갑습니다");
Function<Boolean, String> f = (t) -> t ? "yes" : "no";
String result = f.apply(true);
String result2 = f.apply(false);
System.out.println(result);
System.out.println(result2);
}
}
메소드 레퍼런스 (Java 1.8 이상)