Lambda_expression(1)
자바의 정석의 책을 중심으로 정리하였습니다.
JDK1.8 부터 추가된 람다식(Lambda) 등장
Lambda expression이란 ?
메서드를 하나의의 식으로 표현한것.
함수를 간략하면서도 명확한 식으로 표현할 수 있게 해준다.
메서드를 람다식으로 표현하면, 메서드의 이름과 반환값이 없어지므로, 람다식을 익명함수(anonymous function) 이라고도 한다.
int[] arr= new int[5];
Arrays.setAll(arr, (i) -> (int)(Math.random()*5)+1);
위의 람다식 (i) -> (int)(Math.random()*5)+1 을 메서드로 표현하면 다음과 같다
int method(){
return (int)(Math.random()*5) +1;
}
lambda expression 작성하기
반환값이 있는 메서드의 경우, return문 대신 Expression으로 대신 할 수 있다.
식의 연살 결과가 자동적으로 반환값이 됨,
- 중요한점은 '문장'이 아닌 식(Expression)이므로 끝에 ; 를 붙이지 않는다.
(int a, int b) -> { return a>b ? a:b ;} —> (int a, int b) -> a>b? a:b
문장(statement) 식 (expression)
return a>b ? a:b ; a>b? a:b
- 람다식에 선언된 매개변수의 타입은 추론이 가능한 경우는 생략이 가능한 경우는 생략 가능
람다식에 반환타입이 없는 이유는 항상 추론이 가능하기 때문이다.
(int a, int b) -> a>b? a:b —> (a,b) -> a>b? a:b
두 매개변수 중 어느 하나의 타입만 생략하는것은 허용되지 않는다. - 매개변수가 하나일 경우에는 괄호를 생략 가능하다.
(a) -> aa —> a -> aa (int a) -> a/a —> int a-> a/a ( 에러 ) - 괄호{ } 안의문장이 하나일 경우에는 괄호 생략 가능
(String name, int i) -> { System.out.println(name+"="+ i ) ;} 은 다음과 같이 만들수 있다.
(String name, int i) -> System.out.println(name+"="+ i ) 여기서는 ; 를 제거 해야한다.
함수형 인터페이스( functional interface)
자바에서 모든 메서드는 클래스 내에 포함되어야하는데, 람다식은 어떤 클래스에 포함되는 것일까??
람다식은 익명 클래스의 객체와 동등하다. 라고 되어있는데 무슨말일까??
package lambda_expression;
public class lambda01 {
public static void main(String[] args) {
//익명클래스의 객체의 생성
MyFunction f1 = new MyFunction() {
@Override
public int max(int a, int b) {
return a > b ? a : b;
}
};
int big = f1.max(5, 3);//익명 객체의 메서드를 호출
System.out.println(big);
//람다식으로 표현으로 바꿈
MyFunction f2 = (int a, int b) -> a > b ? a : b; // 익명 객체를 람다식으로 대체
int big2 = f2.max(6,3);//익명 객체의 메서드 호출
System.out.println(big2);
}
}
결과
5
6
람다식과 동등한 메서드가 정의 되어 있는 것이어야한다.!!
그래야만 참조변수로 익명 객체의 메서드를 호출할 수 있기 때문이다.
MyFunction인터페이스를 구현한 익명 객체를 람다식으로 대체가 가능한 이유
: 람다식도 실제로는익명객체이고, MyFunction 인터페이스르 구현한 객체의 메서드 max()와 람다식의 매개변수의 타입과 개수 그리고 반환값이 일치 하기 때문이다.
람다식을 다루기 위한 인터페이스를 '함수형 인터페이스(functional interface) 라고 부르기로 함
람다식과 인터페이스의 메서드가 1:1 로 연결될 수 있기 때문
기존의 인터페이스의 메서드를 구현하여 사용하는 것은 아래와 같다.
List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");
Collections.sort(list, new Comparator<String>(){
@Override
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}
});
이것을 람다형식으로 변경해주면 ??
List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");
Collections.sort(list,(s1,s2) -> s2.compareTo(s1));
이렇게 간단하게 사용할 수 있다.
Collections클래스의 sort 메서드와 Comparator 인터페이스를 살펴 보았다
public class Collections {
// Suppresses default constructor, ensuring non-instantiability.
private Collections() {
}
....
@SuppressWarnings({"unchecked", "rawtypes"})
public static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
...
}
Collections의 sort의 파라미터는 Compator 인터페이스이며,
Comparator인터페이스는 @FunctionalInterface 를 어노테이션으로 선언되어 있었다.
@FunctionalInterface
public interface Comparator<T> {
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.<p>
...
*/
int compare(T o1, T o2);
...
//p 798
메서드의 매개변수가 @FunctionalInterface 로 정의된 타입의 인터페이스라면 메서드를 호출할때 람다식을 참조하는 참조변수를 매개변수로 지정해야한다는 뜻
void aMethod(Function f){
f.myMethod();
}
...
MyFunction f = () -> System.out.println("myMethod()");
aMethod(f);
종합 한 코드를 보면 다음과 같다.
package lambda.example;
@FunctionalInterface
interface LambdaFunction {
void run(); //public abstract void run()
}
public class LambdaEx1 {
//매개변수의 타입이 LambdaFunction인 메서드
static void execute(LambdaFunction f) {
f.run();
}
//반환 타입이 LambdaFunction인 메서드
static LambdaFunction getMyFunction() {
LambdaFunction f = () -> System.out.println("f3.run()");
return f;
}
public static void main(String[] args) {
//람다 식으로 LambdaFunction run()을 구현
LambdaFunction f1 = ()->System.out.println("f1.run()");
LambdaFunction f2 = new LambdaFunction(){//익명 클래스로 run()을 구현
@Override
public void run() {
System.out.println("f2.run()");
}
};
LambdaFunction f3 = getMyFunction();//이미 함수로 LambdaFunction의 run을 구현
f1.run();
f2.run();
f3.run();
execute(f1);
execute(()->System.out.println("run()"));
}
}
'ProgramLanguage > Java' 카테고리의 다른 글
Java 와 객체 지향 (0) | 2019.12.03 |
---|---|
Java jar파일 만들기 (0) | 2019.08.04 |
인터페이스와 추상클래스 (0) | 2019.06.10 |
익명클래스(Anonymous Class) (0) | 2019.06.08 |
Java OutOfMemoryError (0) | 2017.12.18 |