본문 바로가기

Programming/과거포스팅

자바 람다식(Java Lambda Expression)

자바 람다식(Java Lambda Expression)



오랜만에 세미나를 다녀왔다. 벌써 스프링5와 자바9에 대한 내용을 다루기 시작했다.

회사에서 간단한 람다식을 사용했지만 8에있는 스트림은 전혀 사용해 보지 못했고, 람다식도 forEach에서만 사용했었다.  너무 늦으면 안되겠다는 생각에 간단히 람다식을 정리해야겠다고 생각했다. 깊이 있는 내용이 아니라 람다의 개념정도만 정리하는 글이다.


1. 람다식이란? 

Java8에서 도입된 문법이다. 많은 사이트에서 람다식을 다음과 같이 정의하고 있다.

- 식별자 없이 실행 가능한 함수 표현식( 코드를 보면 쉽게 이해할 수 있다.)

함수형 프로그래밍 언어에서는 너무나 익숙한 방법이지만 자바에서는 조금 생소할 수 있다. 



2. 람다식의 장점과 단점 ?

람다식의 장점은 정말 단순하다. 

어려운 말들을 다 제외하고 람다의 장점을 설명하자면 간단 명료하다. 바로 코드의 간결화와 이로인한 명확성이다.

단점으로도 여러 문제점들이 있다. 클로저의 미지원이라던지 함수 외부의 값을 변경한다던지, 성능의 문제점등등인데 이 문제점들은 일반적이 경우가 아니다.

해당 이슈들은 복잡한 내용들을 다뤄야 하기 때문에 람다의 개념만 알고 넘어가는 이글에 적절하지 않기 때문에 생략한다. 대규모의 어플리케이션이 아닌 일반 적인 소규모의 어플리케이션에서는 크게 신경쓰지 않아도 될 것 같다.



3. 예제



표현방법


이전방식

public class Main {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("기존 방식");
            }
        }).start();
    }
}

람다식

public class Main { public static void main(String[] args) { new Thread(()->{ System.out.println("람다식"); }).start(); } }


람다식은 코드가 간결해지면서 명확성이 높아진다. 단 문법에 익숙하지 않다면 무슨 코드인지 이해하지 못할 것이다.

위의 코드처럼 매개변수가 없거나 두개이상일 경우 ()->와 같이 괄호를 무조건 넣어야하고 매개변수가 한개라면 괄호를 생략할 수 있다. 매개변수에는 int a처럼 타입을 추가하지 않고 a->{}와 같이 작성 할 경우 타입은 런타임시 자동으로 인식되어진다.

타입이 없는 함수형 언어에서는 너무 일반적이지만 자바에서는 생소할 수 있다.



forEach

import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {

        List<Integer> countArray = Arrays.asList(1,2,3,4,5,6,7);

        //기존방식
        for(Integer count :countArray ) {
            System.out.println(count);
        }

        //람다방식
        countArray.forEach(count->{
            System.out.println(count);
        });
    }
}

내가 람다식을 가장 많이 사용하는 것은 위의 forEach코드이다. 기존방식도 간결해진 for문이지만 람다방식은 더욱더 간결해진 것을 볼 수 있다. 



@FunctionalInterface


자바에서는 메서드를 인자로 넘길 수 없다. 위의 쓰레드를 람다로 구현한 예제에서 어떻게 run()메서드를 인자로 넘겨서 구현을 했을까??

자바에서는 FunctionalInterface라는 것이 Function과 같은 역할을 한다. FunctionalInterface라는 것은 특정 조건을 만족하는 Interface라고 할 수 있다.

많은 블로그들에 정보들이 있는데 간단히 말하면 추상메소드가 하나뿐인 인터페이스다. Runnable 인터페이스에는 run 추상메소드가 하나 있다. 그렇기 때문에 매개변수로 메서드를 사용할 수 있는 것이다.


코드를 보면 더 쉽게 이해할 수 있다.


public class Main {

    public static void main(String[] args) {

        Function func = (int a, int b)-> a+b;

        System.out.println(func.sum(1, 2));
    }

    public interface Function {
        public int sum(int a, int b);
    }
}

Function 인터페이스를 만들고 람다식으로 내부를 구현한 코드다. interface에 @FunctionalInterface 어노테이션을 사용하면 하나의 메서드만 작성이 가능하다.


람다식은 요약하면 별게 없다. 메서드(함수)를 매개변수로 사용할 수 있는 문법이다