ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java]람다식(Lambda expression)이란?
    Java 2022. 1. 17. 00:01
    728x90

    우선 자바에는 큰 변화가 두 번 있었는데 처음은 이전 시간에 다루었던 JDK1.5부터 추가된 제네릭스의 등장이며 또 한 번은 JDK1.8부터 추가된 람다식(Lambda expression)의 등장입니다.

     

    자바는 객체지향 언어입니다.

    하지만 람다식을 활용한다면 기존의 자바를 거의 변경하지 않고 함수형 언어의 기능까지 갖추게 해 줍니다.

    람다식(Lambda expression)이란?

    람다식(Lambda expression)은 메서드를 하나의 '식(expression)'으로 표현한 것입니다.

    메서드를 람다식으로 표현하면 메서드의 이름과 반환 값이 없어지므로, 람다식을 '익명 함수'라고도 합니다.

    '식(expression)'을 사용하여 하나의 메서드 인터페이스를 나타내는 명확하고 간결한 방법을 제공합니다.

     

    람다라는 용어의 기원

    수학 미적분학에 뿌리를 두고 있으며 함수 추상화에 기반한 계산을 표현하기 위한 수학 논리의 공식 시스템입니다.

    첫 번째 x에 3을 넣게 되면 결과로 9가 나올 것을 예상할 수 있습니다.

    이처럼 람다는 함수의 이름이 존재하지 않으며 여러 가지가 생략되어 있어도 해당 내용이 어떤 것인지 어느 정도 유추할 수 있습니다.

     

    람다식의 예시부터 살펴보겠습니다.

    아래의 그림은 랜덤 값을 생성하여  (랜덤 값 * 5) + 1에 해당하는 값을 정수형으로 바꾸어 반환하는 메서드입니다.

    int method(){
    	return (int) (Math.random() * 5) + 1;
    }

    해당 메서드를 람다식으로 작성한다면 어떻게 될까요?

    () -> (int) (Math.random() * 5) + 1 )

     

    위와 아래 코드의 차이점을 살펴보겠습니다.

    함수의 이름(method)과 반환형(int)이 사라지고 return, ; 구문이 사라졌습니다.

     

    메서드와 함수의 차이점

    본질적인 개념은 동일하나 객체지향 개념에서는 함수 대신에 메서드라는 용어를 사용합니다.

    메서드는 특정 클래스에 반드시 속해야 한다는 제약이 있습니다.

    하지만 이제 람다식을 통해 메서드가 하나의 독립적인 기능을 하기 때문에 함수라는 용어를 사용하게 되었습니다.

     

    람다식의 등장 배경

    하나의 CPU 안에 다수의 코어를 삽입하는 멀티 코어 프로세서들이 등장하면서 일반 프로그래머에게도 병렬화 프로그램에 대한 필요성이 생기기 시작했습니다.

     

    이러한 추세에 대응하기 위해 자바 8 에서는 병렬화를 위한 컬렉션(배열, List, Set, Map)을 강화했고, 이러한 컬렉션을 더 효율적으로 사용하기 위해 스트림이 추가되었고 또 스트림을 효율적으로 사용하기 위해 함수형 프로그램이, 다시 함수형 프로그래밍을 위해 람다가, 또 람다를 지원하기 위한 함수형 인터페이스가 나오게 되었습니다.

     

    스트림에 대해서는 추후에 다뤄보도록 하겠습니다.

     

    또한 람다식을 활용한다면 익명 클래스보다 간결하게 표현할 수 있습니다. 이는 아래에서 조금 더 다루어 보겠습니다.

     

     

    람다식 작성방법

    1. 반환 타입 메서드 이름을 제거하고 매개변수 선언부와 몸통 사이에 '->'를 추가한다.

     

    2. 반환 값이 있는 메서드의 경우 return 문 대신 '식(expression)'으로 대신할 수 있습니다. 또한 끝에는 ;을 붙이지 않습니다.( 식의 연산 결과가 자동적으로 반환됩니다)

     

    3. 람다식에 선언된 매개변수의 타입은 추론이 가능한 경우는 생략할 수 있다.

     

    4. 매개변수가 하나라면 괄호를 생략할 수 있다. 단 매개변수의 타입이 있으면 괄호()를 생략할 수 없다.

     

    다음 메서드를 람다식으로 작성해보면서 다시 살펴보겠습니다.

    int max(int a, int b) {
    	return a > b ? a : b;
    }

    1번을 적용해보겠습니다

    1. 반환 타입 메서드 이름을 제거하고 매개변수 선언부와 몸통 사이에 '->'를 추가한다

     

    (int a, int b) -> {
    	return a > b ? a : b;
    }

    이제 2번을 적용해보겠습니다

    2. 반환 값이 있는 메서드의 경우 return 문 대신 '식(expression)'으로 대신할 수 있습니다. 또한 끝에는 ;을 붙이지 않습니다.( 식의 연산 결과가 자동적으로 반환됩니다)

     

    (int a, int b) -> a > b ? a : b

     

    이제 3번을 적용해보겠습니다

    3. 람다식에 선언된 매개변수의 타입은 추론이 가능한 경우는 생략할 수 있다.

     

    (a, b) -> a > b ? a : b

    매개변수가 2개이기 때문에 4번을 적용할 수는 없습니다.

    다른 예시를 통해 4번을 살펴보겠습니다.

    4. 매개변수가 하나라면 괄호를 생략할 수 있다. 단 매개변수의 타입이 있으면 괄호()를 생략할 수 없다.

    (a) -> a * a //OK
    a -> a * a // OK
    
    (int a) -> a * a //OK
    int a -> a * a //에러

     

    람다에 대해 어느 정도 알아보았습니다.

    그러면 실제로 람다식을 적용하는 과정을 알아보겠습니다.

    이전에 함수형 인터페이스에 대해 알아야 합니다.

     

    함수형 인터페이스란?

    단 하나의 추상 메서드만 선언된 인터페이스입니다.

     

    다음은 함수형 인터페이스의 예시입니다.

    이때 @FunctionalInterface라는 어노테이션을 사용하면 추상 메서드가 2개 이상이라면 에러가 발생합니다.

    interface MyFunction {
    	public abstract int max(int a, int b);
    }

    함수형 인터페이스를 사용하기 위해서 익명 클래스를 사용합니다.

    MyFunction f  = new MyFunction() {				
    				public int max(int a, intb) {                			
                                		return a > b ? a : b;                        		
                                        }
                       		};
    int value  = f.max(3,5);

    이때 함수형 인터페이스 타입의 참조 변수로 람다식을 참조할 수 있습니다.

    MyFunction f = (a, b) -> a > b ? a : b ;
    int value = f.max(3, 5);

     

    또한 함수형 인터페이스 타입의 매개변수와 반환타입을 사용할 수 있습니다.

    @FunctionalInterface
    interface MyFunction {
    	void run();
    }
    
    //매개변수의 타입이 함수형 인터페이스(MyFunction)인 메서드
    static void execute(MyFunction f) {
    	f.run();
    }
    
    //반환 타입이 함수형 인터페이스(MyFunction)인 메서드
    static MyFunction getMyFunction(){
    	MyFunction f = () -> System.out.println("f3.run()");
        return f;
    }
    
    
    public static void main(String[] args) {
    	
        MyFunction f1 = () -> System.out.println("f1.run()");
        MyFunction f3 = getMyFunction();
    	
        f1.run(); //f1.run() 출력
        f3.run(); //f3.run() 출력
        execute(f1); // f1.run() 출력
    
    }

     

     

     

     

    출처

    자바의 정석 3rd Edition

    https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html

    https://wonyong-jang.github.io/java/2021/03/12/Java-Lambda-Expressions.html

     

    [Java] 람다 표현식(Lambda Expressions) - SW Developer

    목표 자바의 람다식에 대해 학습하세요. 학습할 것 람다식 사용법 함수형 인터페이스 Variable Capture 메서드, 생성자 레퍼런스 1. 람다식이란? 람다식은 메서드를 하나의 식(expression)으로 표현한 것

    wonyong-jang.github.io

    https://incusdata.site/pan/java/Java-%20J801%20Introduction%20to%20Lambdas.html

     

    Java Lambdas and Streams

    Java 8 is probably the most significant upgrade to the Java programming language since Java 5 intro­duced generics and annotations. The most important features of Java 8 are, without a doubt, lambda expressions and streams. There are a host of new feature

    incusdata.site

     

    'Java' 카테고리의 다른 글

    [Java] java.util.function 패키지란?  (0) 2022.01.22
    [Java] 래퍼 클래스(Wrapper Class)란?  (0) 2022.01.20
    [Java] 내부 클래스란?  (0) 2022.01.11
    [Java] 상속(Inheritance)이란?  (0) 2022.01.06
    [Java] 오버로딩(Overloading)이란?  (0) 2022.01.05

    댓글

Designed by Tistory.