Stream 연산들은 매개변수로 함수형 인터페이스(Functional Interface)를 받도록 되어있습니다.
그리고 람다식은 반환값으로 함수형 인터페이스를 반환하고 있기 때문에 Stream API를 정확히 이해하기 위해 람다식과 함수형 인터페이스에 대해 알고 있어야 한다고 생각합니다.
람다식이란 함수를 간결하게 표현한 것입니다.
// 기존의 방식
리턴타입 메소드명 (매개변수, ...) {
실행문
}
// 예시
public String hello() {
return "Hello World!";
}
// 람다 방식
(매개변수, ... ) -> { 실행문 ... }
// 예시
() -> "Hello World!";
✔️장점
코드를 간결하게 만들 수 있다.
가독성이 높아진다.
함수를 만드는 과정이 없어 생산성이 높아진다.
✔️단점
무명함수는 재사용이 불가능하다.
디버깅이 어렵다.
함수형 인터페이스란 1 개의 추상 메소드를 갖는 인터페이스를 말합니다.
추상 메서드가 하나라는 뜻은 default method 또는 static method 는 여러 개 존재해도 상관 없다는 뜻입니다.
@FunctionalInterface
interface MyInterface<T> {
// abstract method
abstract void myMethod();
// default method
default void Default1() {
System.out.println("Default1");
}
// default method
default void Default2() {
System.out.println("Default2");
}
// static method
static void Static1() {
System.out.println("Static1");
}
// static method
static void Static2() {
System.out.println("Static2");
}
}
매번 함수형 인터페이스를 직접 만들어서 사용하는 건 상당히 번거롭기 때문에
Java 에서는 기본적으로 많이 사용되는 함수형 인터페이스를 제공합니다.

Supplier<String> supplier = () -> "Hello World!";
Consumer<String> consumer = (str) -> System.out.println(str)
Function<String, Integer> function = str -> str.length();
Predicate<String> predicate = (str) -> str.equals("Hello World");
이처럼 람다식을 사용해 함수형 인터페이스를 리턴할 수 있을 뿐만 아니라
변수명::함수이름, Class명::함수이름(new) 로 함수형 인터페이스를 리턴할 수 있습니다.
// Supplier
Supplier<String> supplier = String::new; // 매개변수 없이 String 리턴
// Consumer
Consumer<String> consumer = System.out::println; // 매개변수에 "Hello World!!"를 넣고 값을 출력(println은 void)
consumer.accept("Hello World!!");
// Function
Function<String, Integer> function = String::length; // 매개변수에 "Hello World!!"를 넣고 길이 값을 리턴(length는 void가 아님)
function.apply("Hello World");
// Predicate
Predicate<Boolean> predicate = Objects::isNull; // object를 입력받아 boolean 타입 리턴
이번 글에서는 Stream API를 사용하기 위한 람다식과 함수형 인터페이스를 알아봤습니다
다음에는 생성, 가공, 결과를 낼때 사용하는 메서드들에 대해 알아보겠습니다.