반응형

람다식 표현

람다식 표현이란?

함수( 매서드 )를 간단한 식(expression)으로 표현하는 방법

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

익명 함수(이름이 없는함수, anonymous function)

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

함수와 매서드의 차이

  • 근본적으로 동일. 함수는 일반적 용어, 매서드는 객체지향개념 용어
  • 함수는 클래스에 독립적, 매서드는 클래스에 종속적

람다식 작성하기

① 매서드의 이름과 반환 타입을 제거하고 '->'를 블록{} 앞에 추가한다.

int max(int a, int b){		
	return a > b ? a : b;	
}
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(int a, int b) -> {		
	return a > b ? a : b;	
}

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

(int a, int b) -> {		
	return a > b ? a : b;	
}
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(int a, int b) -> a > b ? a : b

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

(int a, int b) -> a > b ? a : b
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
(a,  b) -> a > b ? a : b

※ 주의 사항

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

// (a) -> a * a
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
a -> a * a // 문제 없음

// (int a) -> a * a
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
int a -> a * a // 에러

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

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

3. 단, 하나 뿐인 문장이 return문이면 괄호{} 생략 불가

(int a, int b) -> { return a > b ? a : b; } // OK
(int a, int b) -> return a > b ? a : b      // 에러 발생

함수형 인터페이스

람다식은 익명 함수가 아니라 익명 객체이다.

( a, b ) -> a > b ? a : b
// 위의 람다식은 밑과 같이 적혀있는것과 비슷하다
new Object(){
	int max(int a, int b){
		return a > b ? a : b;
	}
}

람다식(익명 개체)을 다루기 위한 참조 변수가 필요. 참조 변수의 타입은?

Object obj = new Object(){		
	int max(int a, int b){	
		return a > b ? a : b;
	}
};
// 위와같이 정의한뒤 밑과 같이 사용하려고 해도 에러가 발생한다.
// 위에 정의한 max 메소드는 Object클래스에 정의되어 있지 않기 떄문에 에러가 발생함
int value = obj.max(3, 5);

타입 obj = ( a, b ) -> a > b ? a : b;

  • Object 타입은 람다식 표현을 입력할 수 없다. 그렇기 때문에 함수형 인터페이스를 이용해서 람다식을 사용한다.

함수형 인터페이스

단 하나의 추상 메서드만 선언된 인터페이스

@FunctionalInterface
interface MyFunction{
    public abstract int max(int a, int b);
}

// 익명클래스 클래스의 선언, 객체 생성 동시에 진행됨
MyFunction f = new MyFunction() {
        public int max(int a, int b){
            return a > b ? a : b;
        }
    };
                    
int value = f.max(3, 5); // OK, MyFunction에 max() 가 있음

함수형 인터페이스 타입의 참조 변수로 람다식을 참조할 수 있음

MyFunction f = (a, b) -> a > b ? a : b;
int value = f.max(3, 5); // 실제로는 람다식(익명 함수)이 호출됨
/*
//Ex1)
List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");

Collections.sort(list, new Comparator<String>(){
            public int compare(String s1, String s2) -> {            
                return s2.compareTo(s1);        
            }            
        });                

@FunctionalInterface
interface Comparator<T>{
    int compare(T o1, T o2);
}
*/                
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //

List<String> list = Arrays.asList("abc","aaa","bbb","ddd","aaa");

Collections.sort(list, (s1,  s2) - > s2.compareTo(s1));

@FunctionalInterface
interface Comparator<T>{
    int compare(T o1, T o2);
}

함수형 인터페이스 타입의 매개변수, 반환 타입

// 함수형 매개변수    
// 함수형 인터페이스를 인수로 받는다는건 람다식 메소드을 받겠다는 이야기     
void aMethod( MyFunction f ){    
    f.myMethod(); // MyFunction에 정의된 매서드 호출
}    
    
@FunctionalInterface    
interface Comparator<T>{    
    int compare(T o1, T o2);
}    
    
MyFunction f = () -> System.out.println("myMethod()");
aMethod(f);    
// ↓ 메소드를 읽기전에 람다식을 직접 입력해주는 형태도 가능
aMethod(() -> System.out.println("myMethod()"));
// 함수형 반환타입
/*
MyFunction myMethod(){
	MyFunction f = () -> {};
	return f;
}
*/
// ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ //
MyFunction myMethod(){	
	return () -> {};
}

[참고 자료]

[자바의 정석 - 기초편] ch14-1~4 람다식이란? 람다식 작성하기

[자바의 정석 - 기초편] ch14-5,6 함수형인터페이스

반응형

+ Recent posts