람다 표현식
이란 메서드로 전달할 수 있는 익명 함수
를 단순화 한 것
- 익명 : 보통 메서드와 달리 이름이 없기에
익명
이라고 표현한다. - 함수 : 메서드처럼 특정 클래스에 종속되지 않기 때문에
함수
라고 부른다. - 전달 : 람다 표현식을 메서드
인수
로 전달하거나변수
로 저장할 수 있다. - 간결성 : 익명 클래스처럼 많은 코드를 구현할 필요가 없다.
Comparator<Apple> byWeight = new Comparator<Apple>(){
public int compare(Apple a1, Apple a2){
return a1.getWeight.compareTo(a2.getWeight);
}
}
Comparator<Apple> byWeight = (Apple a1, Apple a2)
-> a1.getWeight().compareTo(a2.getWeight());
Comparator :
comareTo
메서드를 제공하는 함수형 인터페이스compareTo : 값이 같으면
true
, 다르면false
이렇게 람다를 사용하면 코드가 훨씬 간결해진다.
람다를 사용한 코드에서 볼 수 있듯 람다는 3부분으로 나뉘는데,
- 파라미터 리스트 : Comparator의 compare 메서드 파라미터(사과 2개) -
(Apple a1, Apple a2)
- 화살표 : 리스트와 바디를 구분함 -
->
- 람다 바디 : 람다의 반환값에 해당하는 표현식이다. -
a1.getWeight().compareTo(a2.getWeight());
(String s) -> s.length();
(Apple a) -> a.getWeight() > 150 //boolean 반환
- 하나의 파라미터를 가지므로 return 문을 사용하지 않아도 된다.
(int x, int y) -> {
System.out.println("Result : ");
System.out.println(x + y);
}
- 반환 값이 void 이기 때문에 return 문을 사용하지 않는다.
중괄호
를 사용해서 여러 문장을 포함할 수 있다.
() -> 42
- 파라미터가 없으며 int 42를 반환한다.
(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());
- 파라미터 2개를 가지며 두 사과의 무게 비교 결과를 반환한다.
람다 규칙에 맞지 않는 람다 표현식을 고르시오.
() -> {}
() -> "Raoul"
() -> {return "Mario";}
(Integer i) -> return "Alan" + i;
(String s) -> {"Iron Man"}
그래서 정확히 어디에서 람다를 사용할 수 있다는 건지 궁금할 수 있다. 바로 함수형 인터페이스라는 문맥에서 람다 표현식을 사용할 수 있다.
함수형 인터페이스
는 정확히 하나의 추상 메서드를 지정하는 인터페이스이다.
다음 인터페이스 중 함수형 인터페이스는 어느 것인가?
public interface Adder {
int add(int a, int b);
}
public interface SmartAdder extends Adder {
int add(double a, double b);
}
public interface Nothing {
}
package anonymous;
public class UseAnonymousClass{
public static void process(Runnable r) {
r.run();
}
public static void main(String[] args) {
Runnable r1 = () -> System.out.println("Hello Lambda!!"); // 1
Runnable r2 = new Runnable() { // 2
@Override
public void run() {
System.out.println("Hello Lambda2!!");
}
};
process(r1);
process(r2);
process(() -> System.out.println("Hello Lambda3!!"));
}
}
람다 사용
Runnable
이라는익명 함수 클래스
를 사용함
Supplier<String> supplier = () -> "Hello Lambda!!";
System.out.println(supplier.get());
Consumer<String> consumer = (str) -> System.out.println(str.split(" ")[0]);
consumer.andThen(System.out::println).accept("Hello Lambda!!");
Function<String, Integer> function = (str) -> str.length();
System.out.println(function.apply("Hello Lambda!!"));
Predicate<String> predicate = (str) -> str.equals("Hello Lambda!!");
System.out.println(predicate.test("hello lambda!!"));
위의 내용을 보다보면 "아니 람다 쓰려면 무조건 함수형 인터페이스를 써야하나?" 라는 생각이 들수도있다.
하지만 함수형 인터페이스는 우리가 정의할 수도 있는데 바로 @FunctionalInterface
을 사용하는 방법이다.
@FunctionalInterface
interface MyLambdaFunction {
int multiply(int a, int b);
}
public static void main(String[] args) {
MyLambdaFunction myLambdaFunction = (int a, int b)
-> Math.multiplyExact(a, b);
System.out.println(myLambdaFunction.multiply(10, 30));
}
이런 식으로 하나의 추상 메서드를 지정하는 메서드를 만들어서 @FunctionalInterface
로 지정해주면
사용자가 정의한 함수형 인터페이스
가 되는 것이다.
람다식을 사용하다 보면 코드가 약간 길어질 수 있다.
Function<String, Integer> function = (str) -> str.length();
위와 같이 매개변수를 던져주고 그 길이를 반환하는 람다식이다. 하지만 **::**를 사용하면 메서드의 길이를 줄일 수 있다.
Function<String, Integer> funciton = String::length;
같은 역할을 하는 메서드인데 더 짧게 만들어졌다.
하지만 무작정 메서드 참조 단축 표현을 사용한다면 오히려 그 길이가 더 길어질 수 있는데, 다음과 같은 상황이다.
int length1 = "abcd".length();
Function<String, Integer> shortFunction2 = String::length;
Integer length2 = shortFunction2.apply("abcd");
단순히 문자열 "abcd"의 길이를 구하는 메서드이지만 굳이 함수형 인터페이스까지 쓰면서 메서드 단축 표현을 사용하면 코드가 훨씬 길어지는 사태가 발생할 수 있다.
결론은 람다식을 사용하면 메서드의 길이가 길어질 수 있고, 이는 :: 로 줄일 수 있다.
하지만 굳이 사용하지 않아도 되는 곳에서 무작정 쓰려고하면 오히려 코드가 길어지는 상황이 발생할 수 있으니 생각해보고 사용하자
![](../../../../../../var/folders/ms/14322fys69xdtw3zrnlz5wd80000gn/T/TemporaryItems/NSIRD_screencaptureui_Oa7TtR/스크린샷 2022-06-22 오후 1.52.41.png)