백엔드

java 8 Lambda Expression

CyberI 2016. 5. 2. 02:09

java 언어에 람다 표현식을 도입하려는 '프로젝트 람다'가 2009년에 시작되고 5년만인 2014년에 자바 8이 릴리즈 되었다.  오늘은 이에 대해 포스팅 해보고자 한다.

함수형 언어에서 function은 'First-Level Class' 이므로 변수에 할당하고 파라미터로 전달될수 있다. 하지만 java는 함수형 언어가 아니므로 당연히 함수를 지원하지 않는다. 하지만 자바 8에서는 람다를 이용하여 java에서 method가 아닌 function을 사용할 수 있다. 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부르며 이는 메서드처럼 파라미터 리스트, 바디, 반환형식 등을 포함한다. 기본적인 람다 표현식의 기본 적인 문법 형태는 다음과 같다. 

(arg1, arg2...) -> { body }

저 눈에 익숙하지 않은 문법이 도대체 무엇인지 한번 살펴 보도록 하자.  자바에는 단 하나의 메서드만을 선언한 여러가지 interface들이 있다. Runnable 이라던지.. Comparator 이라던지..  이러한 인터페이스들을 '함수형 인터페이스' 라고 정의하며 이를 람다로 표현 할 수 있게 하였다. 무슨 소리인지 다음의 예제를 보도록 하자.


위의 예제는 Thread 처리를 위해 보통 사용 되었던 형태이다. Runnable이라는 interface를 구현한 클래스를 어딘가에  작성하고 그것을 이용해 Thread를 처리 하였다.


위 예제는 runnable을 구현하는 class를 정의하지 않고  Anonymous Inner-Class( 익명 내부클래스 )를 통해 한번에 처리 하였다. 


java 8의 람다식으로 표현하여 thread를 구동한 모습이다.  자 이제 다음의 함수를 한번 천천히 살펴 보자.

먼저 람다식의 무조건  단 하나의 메서드를 가진 함수형 인터페이스에 사용할 수 있다.  Runnable interface는 run() 이라는 하나의 메소드만 가지고 있으므로 이 조건을 만족한다. 

-> 를 기준으로 왼쪽은 파라미터 리스트 오른쪽은 행위이다.  Runnable 인터페이스의 run() 메소드는 인자가 없으므로 왼쪽은 () 가 된다. 오른쪽은 실제 우리가 run 메서드 내부에 정의한 행위에 대한 기술이다.  


기본적인 람다의 표현식에 대해 설명하였다. 단순히 문법 자체만 짧아진것이라면 분명 큰 장점이 아닐것이다. 람다식을 다른 함수에 전달 할 수 있다면 값 뿐만 아니라 행위까지도 전달 할수 있다. 이를 이용하면 더욱 유연하고 재사용 가능한 API를 만들 수있다.  다음의 예제를 보자.


모든 수를 더하는 메서드

 짝수인 수만 더하는 메서드


위의 예제에서 보면 numbers라는 List를 받아 각자 다른 방식으로 합을 계산해 내는 메서드가 있다. 두 메서드는 동일하게 숫자의 list를 받으며 안쪽에서 처리되는 방식만 약간 다르게 처리 될 뿐이다. 이를 람다식을 이용하여 좀더 유연한 API로 만들어보자.


위 메서드는 기존과 다르게 2번째 인자로 Predicate라는 함수형 인터페이스를 인자로 받는다. 이는 자바 8에서 추가된 또 다른 함수형 인터페이스이다. 이처럼 다른 함수를 인자로 받거나 그 결과로 함수를 반환하는 것을 고차함수라 한다. 다음을 다시 람다식에 적용 시켜 보면 다음과 같이 간단하게 표현 할 수 있다.