프로그래밍/자바

[Java] 람다식(Lambda Expressions)

1. 익명 클래스

자바에는 익명클래스를 통해서

재사용 되지도 않을 클래스가 계속 쌓이는것을 막을 수 있다.

대표적으로 쓰레드를 생성할때 아래와 같은 방법을 주로 사용한다.

Thread t = new Thread(new Runnable() {
    @Override
    public void run() {
        while (true) {
            System.out.println(Thread.currentThread().getName() + " : hello world");
        }
   }
});

하지만 자바스크립트에 익숙한 사람이라면

위의 코드마저도 자바스크립트에서 콜백을 사용하는 방식과 비교해 보면

불필요한 코드가 굉장히 많다고 느껴질것이다.

2. 함수적 인터페이스

Runnable 인터페이스를 까보면 아래와 같다

@FunctionalInterface
public interface Runnable{
    public abstract void run();
}

메서드가 오직 run밖에 없다

이렇게 구현할 메서드가 하나밖에 없는 인터페이스를 함수적 인터페이스라고 한다.

메소드가 여러개 있는 인터페이스를 구현할 때 메서드 몸체만 적어두면 그게 무슨 메서드를 구현한건지

모를텐데, 함수적 인터페이스 에서는 메서드 몸체만 있어도 되지 않을까?

따라서 함수적 인터페이스를 익명클래스로 만들때는

파라미터와 함수몸체만 적어주고싶은 생각이 들것같다.

3. 람다식

Thread의 생성자 중 하나는 Runnable을 파라미터로 받는다.

그렇다면 Thread 생성자에서 new Runnable을 적어주지 않아도

컴파일러가 추론할 수 있지 않을까?

이렇게 불필요한 코드는 줄이고자 하는 염원이 자바8에 반영되서

아래와 같은 람다 표현식으로 기존 익명클래스보다 더 간결하게 코딩하는것이 가능해졌다.

Thread t2 = new Thread(()->{
    while(true){
        System.out.println(Thread.currentThread().getName() + " : hello wolrd");
    }
});

4. 표준 API에서 제공되는 함수적 인터페이스

종류 특징 설명
Consumer 매개값은 있고, 리턴값은 없음 매개값 -> Consumer
Supplier 매개값은 없고, 리턴값은 있음 Supplier -> 리턴값
Function 매개값도 있고, 리턴값도 있음 주로 매개값을 리턴값으로 매핑(타입 변환) 매개값 -> Function -> 리턴값
Operator 매개값도 있고, 리턴값도 있음 주로 매개값을 연산하고 결과를 리턴 매개값 -> Operator -> 리턴값
Predicate 매개값은 있고, 리턴 타입은 boolean 매개값을 조사해서 true/false를 리턴 매개값 -> Predicate -> boolean

람다식으로 작성되는 함수의 기능별로 인터페이스의 종류가 나눠진다.

각 종류별로 구체적인 인터페이스들이 많이 있다.

5. 람다식과 스트림

자바8에서 추가된 기능중 스트림은 람다식과 함께 자바 프로그래밍이 더욱더 간단해지게 만든다.

IntStream.range(1, 6)
    .map(num -> num * num)
    .forEach(num -> System.out.println(num));

각각의 스트림 처리 메서드들은 함수적 인터페이스를 파라미터로 받는다.

스트림 처리과정 중에서 세부적으로 어떻게 처리될지만 명시해 주면 자유자재로 스트림을 조작할 수 있다.