1. 람다 표현식 : 익명 함수
Java 8부터 람다(lambda)식을 지원한다. 자바에서 람다식이란, '익명 함수'이다. 익명이란 이름을 특정하지 않음 내지는 이름없음을 뜻하는데, 정확히 무슨 의미일까?
일단 다음과 같은 AddCalculator 인터페이스를 보자. 두 정수를 인자로 받아 특정 계산을 수행하는 operate() 메소드를 가지고 있다. 메소드 body는 없으므로 어떤 로직을 수행할지는 구현체가 결정한다.
public interface Calculator {
public int operate(int x, int y);
}
이제 Calculator 인터페이스를 익명 클래스로 구현한 뒤, 덧셈 연산을 수행하도록 operate() 메소드를 구현하자. 그 뒤 1+2 연산을 수행해보자!
public class CalculatorRunner {
public static void main(String[] args) {
Calculator addCalculator = new Calculator() {
@Override
public int operate(int x, int y) {
return x+y;
}
};
System.out.print("1 + 2의 결과값은 ? : ");
System.out.println(addCalculator.operate(1,2));
}
}
코드의 결과는 간단하므로 생략.
음. 단순히 add() 메소드 하나만 있는 인터페이스를 사용하는데 너무 번거롭다. 참조 변수를 만들고, 객체를 생성하고, operate를 재정의하고... 어차피 구현체 메소드가 하나밖에 없을거, 굳이 그 인터페이스를 구현한 클래스에 @Overrrde로 함수를 명명할 필요도 없을 것 같고 너무 길기도 하다. 해당 인터페이스의 메소드 기능 하나만 간단하게 사용할 수 있도록 하면 안될까?
-에서 나온 것이 람다식이다. 메소드가 하나인 인터페이스를 사용할 것이라면 위 과정을 전부 거칠 필요 없이, 해당 메소드 하나만 구현하면 되는 일이다.
익명 클래스 말고, 람다식(익명 함수)을 이용한 코드를 살펴보자. 앞선 CalculatorRunner과 기능은 완전 동일하다.
public class CalculatorRunner2 {
public static void main(String[] args) {
AddCalculator addCalculator = (x,y) -> x+y;
System.out.print("1 + 2의 결과값은 ? : ");
System.out.println(addCalculator.add(1,2));
}
}
코드가 훨씬 깔끔해졌다. 이것이 람다식이다.
2. @FunctionalInterface
람다 표현식은 functional interface에만 사용 가능하다. functional interface는 앞서 살펴본 AddCaluculator의 예시와 같이, 메소드가 하나만 존재하는 인터페이스이다. 생각해보면 당연한게, 구현해야 할 메소드가 여러개라면 이름 없이 메소드 구분이 어려우므로 '익명'이 될 수 없다.
기본적으로 자바에서 람다식을 표현할 때는 다음과 같은 syntax를 따른다.
// (<매개 변수 목록>) <화살표 토큰> {<처리식>}
(x, y) -> { }
인자를 갖지 않는 메소드라면 소괄호 안이 비어있어도 되고, 메소드의 body가 한 줄이라면 처리식의 {} 중괄호를 생략해도 된다. 예컨데, 아래와 같이 쓰여도 된다는 소리다.
public class RunnableExample {
public static void main(String[] args) {
Thread thread = new Thread(() ->
System.out.println("runnable interface는 functionl interface입니다."));
thread.start();
}
}
자바에서 스레드를 생성하는 방법엔 두 가지가 있는데, Thread 클래스를 extends 하거나 위와 같이 Runnable 인터페이스를 구현하는 방법이다. Runnable 인터페이스에는 단 한 가지의 메소드, run()만이 존재한다.

자바랭 패키지의 Runnable 인터페이스를 보면, 위와 같이 @FunctionalInterface 어노테이션이 붙은 것을 알 수 있다. 이렇게 익명함수 사용에 대한 컨벤션으로, functional interface엔 어노테이션을 붙여주는 것이 좋다.
funtional interface, 즉 함수형 인터페이스를 알맞게 구현하려면 해당 인터페이스가 정의해놓은 메소드의 시그니처를 잘 따라야 한다. 메소드 파라미터의 개수, 파라미터 타입, 리턴 타입이 모두 일치해야 한다는 뜻이다. 그렇다면 원하는 시그니처의 메소드를 만들기 위해 함수형 인터페이스를 하나하나 선언하고 구현해야 할까? 물론 그래도 되지만, 자바에선 일반적으로 사용할만한 함수형 인터페이스를 제공한다.
1. Predicate<T>
test(T object) 메소드를 가지며, 객체에 대한 비교 결과 boolean값을 제시한다.
public class PredicateRunner {
public static void main(String[] args) {
Predicate<String> predicate = (str) -> str.equals("Hello World!");
System.out.println(predicate.test("Hello World!"));
System.out.println(predicate.test("Hello Word!"));
}
}
2. Supplier<T>
반환 값만을 가진 T get() 메소드가 있다.
public class SupplierRunner {
public static void main(String[] args) {
Supplier<String> supplier = () -> "Hello World!";
System.out.println(supplier.get());
}
}
3. Consumer<T>
반환값 없이, T 타입 인자를 가지고 일련의 로직을 수행하는 accept() 메소드가 있다.
public class ConsumerRunner {
public static void main(String[] args) {
Consumer<String> consumer = (str) -> System.out.println(str);
consumer.accept("Hello World!");
}
}
4. Function<T, R>
T타입 인자를 받고 R타입 인자를 return하는 apply() 메소드가 있다.
public class FunctionRunner {
public static void main(String[] args) {
Function<Integer, String> myFunction = (intParam) -> "Hello " + intParam + "!";
System.out.println(myFunction.apply(0));
}
}
이 외에도 BinaryOperator 등 자바 진영에서 제공하는 함수형 인터페이스는 더 많다.
3. Method Reference
함수형 인터페이스를 구현할 때, '메소드 참조' 라는 것도 가능하다. 이는 일반적인 메소드를 함수형 인터페이스의 구현체로써 사용하는 것이다. 앞서 살펴봤던 Consumer의 예시를 가져와보면, 인자로 받은 문자열 객체를 단순히 System.out.println() 시킬 뿐이다. println 메소드 자체가 consumer의 accept 메소드가 될 수 있을 것 같다.
public class MethodReference {
public static void main(String[] args) {
Consumer<String> consumer = System.out::println;
consumer.accept("Hello World!");
}
}
Consumer을 위와 같이 구현하면 이전의 예시와 100% 똑같이 동작한다.
함수형 인터페이스의 메소드와 method reference로 쓰려는 메소드의
- 파라미터 개수
- 파라미터 타입
- return 타입
이 일치했을 때, 위와 같이 객체::메소드 syntax로 method reference를 사용할 수 있다.
다음은 이와같은 람다식을 유용하게 쓸 수 있는 Stream에 대해 작성하겠다.
REFERENCE
https://bamdule.tistory.com/75
[Java] 람다(Lambda) 란?
1. 람다 함수(Lambda Function)란? 람다 함수는 함수형 프로그래밍 언어에서 사용되는 개념으로 익명 함수라고도 한다. Java 8 부터 지원되며, 불필요한 코드를 줄이고 가독성을 향상시키는 것을 목적
bamdule.tistory.com
1. 람다 표현식 : 익명 함수
Java 8부터 람다(lambda)식을 지원한다. 자바에서 람다식이란, '익명 함수'이다. 익명이란 이름을 특정하지 않음 내지는 이름없음을 뜻하는데, 정확히 무슨 의미일까?
일단 다음과 같은 AddCalculator 인터페이스를 보자. 두 정수를 인자로 받아 특정 계산을 수행하는 operate() 메소드를 가지고 있다. 메소드 body는 없으므로 어떤 로직을 수행할지는 구현체가 결정한다.
public interface Calculator {
public int operate(int x, int y);
}
이제 Calculator 인터페이스를 익명 클래스로 구현한 뒤, 덧셈 연산을 수행하도록 operate() 메소드를 구현하자. 그 뒤 1+2 연산을 수행해보자!
public class CalculatorRunner {
public static void main(String[] args) {
Calculator addCalculator = new Calculator() {
@Override
public int operate(int x, int y) {
return x+y;
}
};
System.out.print("1 + 2의 결과값은 ? : ");
System.out.println(addCalculator.operate(1,2));
}
}
코드의 결과는 간단하므로 생략.
음. 단순히 add() 메소드 하나만 있는 인터페이스를 사용하는데 너무 번거롭다. 참조 변수를 만들고, 객체를 생성하고, operate를 재정의하고... 어차피 구현체 메소드가 하나밖에 없을거, 굳이 그 인터페이스를 구현한 클래스에 @Overrrde로 함수를 명명할 필요도 없을 것 같고 너무 길기도 하다. 해당 인터페이스의 메소드 기능 하나만 간단하게 사용할 수 있도록 하면 안될까?
-에서 나온 것이 람다식이다. 메소드가 하나인 인터페이스를 사용할 것이라면 위 과정을 전부 거칠 필요 없이, 해당 메소드 하나만 구현하면 되는 일이다.
익명 클래스 말고, 람다식(익명 함수)을 이용한 코드를 살펴보자. 앞선 CalculatorRunner과 기능은 완전 동일하다.
public class CalculatorRunner2 {
public static void main(String[] args) {
AddCalculator addCalculator = (x,y) -> x+y;
System.out.print("1 + 2의 결과값은 ? : ");
System.out.println(addCalculator.add(1,2));
}
}
코드가 훨씬 깔끔해졌다. 이것이 람다식이다.
2. @FunctionalInterface
람다 표현식은 functional interface에만 사용 가능하다. functional interface는 앞서 살펴본 AddCaluculator의 예시와 같이, 메소드가 하나만 존재하는 인터페이스이다. 생각해보면 당연한게, 구현해야 할 메소드가 여러개라면 이름 없이 메소드 구분이 어려우므로 '익명'이 될 수 없다.
기본적으로 자바에서 람다식을 표현할 때는 다음과 같은 syntax를 따른다.
// (<매개 변수 목록>) <화살표 토큰> {<처리식>}
(x, y) -> { }
인자를 갖지 않는 메소드라면 소괄호 안이 비어있어도 되고, 메소드의 body가 한 줄이라면 처리식의 {} 중괄호를 생략해도 된다. 예컨데, 아래와 같이 쓰여도 된다는 소리다.
public class RunnableExample {
public static void main(String[] args) {
Thread thread = new Thread(() ->
System.out.println("runnable interface는 functionl interface입니다."));
thread.start();
}
}
자바에서 스레드를 생성하는 방법엔 두 가지가 있는데, Thread 클래스를 extends 하거나 위와 같이 Runnable 인터페이스를 구현하는 방법이다. Runnable 인터페이스에는 단 한 가지의 메소드, run()만이 존재한다.

자바랭 패키지의 Runnable 인터페이스를 보면, 위와 같이 @FunctionalInterface 어노테이션이 붙은 것을 알 수 있다. 이렇게 익명함수 사용에 대한 컨벤션으로, functional interface엔 어노테이션을 붙여주는 것이 좋다.
funtional interface, 즉 함수형 인터페이스를 알맞게 구현하려면 해당 인터페이스가 정의해놓은 메소드의 시그니처를 잘 따라야 한다. 메소드 파라미터의 개수, 파라미터 타입, 리턴 타입이 모두 일치해야 한다는 뜻이다. 그렇다면 원하는 시그니처의 메소드를 만들기 위해 함수형 인터페이스를 하나하나 선언하고 구현해야 할까? 물론 그래도 되지만, 자바에선 일반적으로 사용할만한 함수형 인터페이스를 제공한다.
1. Predicate<T>
test(T object) 메소드를 가지며, 객체에 대한 비교 결과 boolean값을 제시한다.
public class PredicateRunner {
public static void main(String[] args) {
Predicate<String> predicate = (str) -> str.equals("Hello World!");
System.out.println(predicate.test("Hello World!"));
System.out.println(predicate.test("Hello Word!"));
}
}
2. Supplier<T>
반환 값만을 가진 T get() 메소드가 있다.
public class SupplierRunner {
public static void main(String[] args) {
Supplier<String> supplier = () -> "Hello World!";
System.out.println(supplier.get());
}
}
3. Consumer<T>
반환값 없이, T 타입 인자를 가지고 일련의 로직을 수행하는 accept() 메소드가 있다.
public class ConsumerRunner {
public static void main(String[] args) {
Consumer<String> consumer = (str) -> System.out.println(str);
consumer.accept("Hello World!");
}
}
4. Function<T, R>
T타입 인자를 받고 R타입 인자를 return하는 apply() 메소드가 있다.
public class FunctionRunner {
public static void main(String[] args) {
Function<Integer, String> myFunction = (intParam) -> "Hello " + intParam + "!";
System.out.println(myFunction.apply(0));
}
}
이 외에도 BinaryOperator 등 자바 진영에서 제공하는 함수형 인터페이스는 더 많다.
3. Method Reference
함수형 인터페이스를 구현할 때, '메소드 참조' 라는 것도 가능하다. 이는 일반적인 메소드를 함수형 인터페이스의 구현체로써 사용하는 것이다. 앞서 살펴봤던 Consumer의 예시를 가져와보면, 인자로 받은 문자열 객체를 단순히 System.out.println() 시킬 뿐이다. println 메소드 자체가 consumer의 accept 메소드가 될 수 있을 것 같다.
public class MethodReference {
public static void main(String[] args) {
Consumer<String> consumer = System.out::println;
consumer.accept("Hello World!");
}
}
Consumer을 위와 같이 구현하면 이전의 예시와 100% 똑같이 동작한다.
함수형 인터페이스의 메소드와 method reference로 쓰려는 메소드의
- 파라미터 개수
- 파라미터 타입
- return 타입
이 일치했을 때, 위와 같이 객체::메소드 syntax로 method reference를 사용할 수 있다.
다음은 이와같은 람다식을 유용하게 쓸 수 있는 Stream에 대해 작성하겠다.
REFERENCE
https://bamdule.tistory.com/75
[Java] 람다(Lambda) 란?
1. 람다 함수(Lambda Function)란? 람다 함수는 함수형 프로그래밍 언어에서 사용되는 개념으로 익명 함수라고도 한다. Java 8 부터 지원되며, 불필요한 코드를 줄이고 가독성을 향상시키는 것을 목적
bamdule.tistory.com