1. 람다 함수 VS 기존 JAVA 익명 함수 , 익명 클래스
기존 Java에서도 익명함수, 익명 클래스는 있었다.
다음과 같이 표현되었다.
Comparator 인터페이스를 상속받는 클래스를 상속 받기 위해 위와 같은 익명클래스를 사용하고 했다.
하지만 보다시피 코드가 너무 길고, 복잡하고, 실제로 나같은경우에도 실수를 너무 많이 했던 부분이다.
람다 함수를 이용하면 같은 코드를 훨씬 더 간결하게 쓸 수 있다.
그러면 람다함수는 어떻게 작동하는 것이고 어떤 문법을 가지고 있는지 알아보자
2. Functional Interface(함수형 인터페이스)
우선 람다함수를 알기 전에 Functional Inteface에 대해서 알고 있어야한다.
Functional Interface는 Interface 중에서 단 하나의 method만 가지고 있는 Interface다.
Java의 가장 대표적인 Functional Interface는 Comparable, Runnable 등이 있다.
단 예외는 있다.
Java 8에 추가된 default method와 static method는 개수에 포함되지 않고, Object의 함수 클래스 또한 포함되지 않는다.
(A functional interface is an interface that has just one abstract method (aside from the methods of Object), and thus represents a single function contract.)
그러므로
다음과 같은 인터페이스는 함수형 인터페이스다.
자바 컴파일러는 @FunctionalInterface라는 annotation을 이용하여 컴파일 타임에
함수형 인터페이스인지를 검사할수있다.
그러나 @FunctionalInterface는 어디까지나 확인 용도이기 때문에 그게 있던 없던 함수인터페이스로 동작한다.
그러므로, 명시적인 용도로만 사용한다.
* <p>However, the compiler will treat any interface meeting the
* definition of a functional interface as a functional interface
* regardless of whether or not a {@code FunctionalInterface}
* annotation is present on the interface declaration.
3. 람다함수
람다 함수는 Java 8 에 새로 추가된 문법 으로 함수형 프로그래밍을 지원하는 기능이다.
함수형 프로그래밍이란 함수 중심으로 프로그래밍으로 하는 것을 말한다.(마치 변수처럼)...
함수란 주어진 입력값에 대해 결과값을 내보내는 것으로 외부환경에 철저히 독립적이라는 특징이 있다.
즉, 상태나 외부변수를 참조하지도 않고 입력값, 결과값(자신의 작업) 집중한다.
다음 예제를 보자
리스트에 들어있는 문자열을 "c로 시작하는 배열의 경우 대문자로 바꿔서 출력하는 함수"를 만든다고 생각하면 보통위에처럼 만들었을 것이다. 하지만 그과정에서 iterator인 i, String s 등의 부수적인 산출물들이 생기는 것을 알수 있다.
반면 아래와 같이 Stream 함수와 람다함수를 사용한 함수형 프로그래밍을 할 경우 각 함수가 명확히 구분되며 외부 변수로부터도 자유로워지고 훨씬 코드가 간결하다는 것을 볼수 있다.
이러한 함수형 프로그래밍을 하기 위해서는 함수가 일급 객체화되어야한다. 자바에서는 함수가 일급객체가 아니기 떄문에 함수를 일급객체화 시키는것이 바로 람다함수이다.
Evaluation of a lambda expression produces an instance of a functional interface (§9.8). Lambda expression evaluation does not cause the execution of the expression's body; instead, this may occur at a later time when an appropriate method of the functional interface is invoked.
람다식이 평가(evaluation)되면 그 결과 Functional Interface의 인스턴스를 생성한다.( 그 이유는 Functional Interface는 하나의 함수만 가지고 있기 떄문에 명시적으로 그 함수를 가진 인스턴스가 만들어진 다는 것이다.)
즉 람다 함수는 FunctionalInterface의 인스턴스가 된다는 뜻이다.
4. 람다 함수의 표기법
기본적인 람다함수 표기법은 (파라미터1, 파라미터 2 , ) - > { 함수식 } 이다.
그러나 몇 가지 문법이 더 있다.
4-1. 파라미터가 없는 경우
() -> { 함수식 } 로 간단하게 줄일 수 있다.
4-2. 함수가 return 값만 있는 경우
(파라미터) -> x 로 줄일수 있다
이는 (파리미터) -> { return x;}와 동등하다.
4-3 파라미터가 하나만 있는 경우
(int x) -> { return x+1;}
은 x -> x+1로 줄일 수 있다.(괄호 생략 가능)
4-4 함수가 한줄인 경우
(int x) -> { System.out.println(x)}; 는
x -> System.out.println(x) 로 줄일 수 있다.
5. 람다함수의 장단점
장점
1. 코드가 간결해진다. (특히 반복문에서)
2. 일급객체로 함수를 사용할 수 있다.
일급 객체(First-class citizen) 란
변수나 데이터에 할당 할수 있고, 객체의 인자로 넘길 수 있으며, 리턴값으로도 리턴할수있어야한다
.
자바에서 대부분의 객체는 일급객체지만, 함수는 일급객체가 아니다.
(자바에서 일반적인함수를 파라미터로 넘길수 있는지 생각해보자. 참고로, Javascript, C 등에서는 함수가 일급객체다.)
단점
1. 문법이 복잡해서 배우는데 오래 걸린다
2. 함수 재사용 불가
3. 재귀함수를 짤때 부적절함
마지막으로 처음에 들었던 람다함수 예시를 확인하면서 끝내겠다.
이 함수에서 Integer i1, i2) -> i1 - i2 는
FunctionalInterface인 Comparator의 메소드 compare 함수의 구현부가 될 람다 함수이다.
또한 return value만 있는 함수이므로 함수 몸통의 {} , return 키워드를 모두 생략하고 i1 - i2 만 써준것이다.
(함수형 인터페이스에서 하나의 메소드만 있는 이유 또한 저 람다함수가 그 메소드의 구현부가 되기 때문에
하나로 제한했다는 거 또한 추측할 수 있다.)
'알고리즘 > 백준' 카테고리의 다른 글
백준 16934 게임 닉네임 (0) | 2020.08.26 |
---|---|
백준 - 6198 옥상정원꾸미기 (0) | 2020.08.25 |
백준 세부 13905 (0) | 2020.05.29 |
백준 15961 회전초밥 (0) | 2020.05.27 |
백준 2458 키 순서 (0) | 2020.05.14 |