Notice
Recent Posts
Recent Comments
Link
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
Tags
more
Archives
Today
Total
관리 메뉴

rudu_std

람다 표현식 (Lambda Expression) 본문

Java

람다 표현식 (Lambda Expression)

Ru_Du 2024. 7. 24. 19:58

람다 표현식 (Lambda Expression)

람다 표현식(lambda expression)이란 함수형 프로그래밍을 구성하기 위한 함수식이며,

간단히 말해 자바의 메소드를 간결한 함수 식으로 표현한 것.

—람다식의 장점과 제한사항—

장점:

  • 간결함 : 익명 클래스의 불필요한 코드 제거.
  • 가독성 : 코드가 짧아져서 더 읽기 쉬워짐.
  • 함수형 프로그래밍 지원 : 순수 함수 스타일의 코딩 가능.

제한사항:

  • 디버깅 : 람다식 내부의 코드를 디버깅하기 어려울 수 있음.
  • 명확성 : 지나치게 복잡한 람다식은 오히려 가독성을 떨어뜨릴 수 있음.
  • 제한된 사용 범위 : 람다식은 함수형 인터페이스와만 사용 가능.

람다식은 자바에서 함수형 인터페이스를 구현할 때 사용됩니다. 따라서 람다식은 함수형 인터페이스와 함께 사용되어야 합니다.

함수형 인터페이스는 오직 하나의 추상 메서드만 정의된 인터페이스를 의미합니다.

함수형 인터페이스란?

함수형 인터페이스는 오직 하나의 추상 메서드만 정의된 인터페이스 입니다. 자바 8부터 @FunctionalInterface 어노테이션을 사용하여 함수형 인터페이스를 명시적으로 정의할 수 있습니다.

이 애너테이션은 해당 인터페이스가 함수형 인터페이스임을 표시하며, 만약 두 개 이상의 추상 메서드를 가지면 컴파일 오류를 발생시킵니다.

  • 하나의 추상 메서드만 있어야 한다.
  • 기본 메서드(default)와 정적 메서드(static)는 여러 개가 있을 수 있다.

예제: 함수형 인터페이스

interface MyFunctionalInterface1 {

    void singleAbstractMethod();  // 하나의 추상 메서드
}
/////////////////////////////////////////////////////////////////////////////////////
interface MyFunctionalInterface2 {
		void singleAbstractMethod();  // 하나의 추상 메서드
    
    default void defaultMethod() {
        System.out.println("This is a default method");
    }

    static void staticMethod() {
        System.out.println("This is a static method");
    }
}
//두개의 인터페이스 모두 함수형 인터페이스
//MyFunctionalInterface2는 기본 메서드와 정적 메서드를 가질 수 있지만, 
//추상 메서드가 하나만 존재하기 때문에 함수형 인터페이스라고 할 수 있다.
//람다 표현 전 메서드
int add(int x, int y) {
	return x + y;
}

// 위의 메서드를 람다 표현식을 이용해 아래와 같이 단축 가능 (메서드 반환 타입, 메서드 이름 생략)
(int x, int y) -> {
	return x + y;
};

// 매개변수 타입도 생략 가능.
(x, y) -> {
	return x + y;
};

// 함수에 리턴문 한줄만 있을 경우 더욱 더 단축 가능. (중괄호, return 생략)
(x, y) -> x + y;

적용 예제

interface Adder {
    int add(int x, int y);
}

public class Main {
    public static void main(String[] args) {
        Adder adder = new Adder() {
            @Override
            public int add(int x, int y) {
                return x + y;
            }
        };
        
        System.out.println(adder.add(5, 3));  // 출력: 8
    }
}
/////////////////////////////////////////////////////////////////////

interface Adder {
    int add(int x, int y);
}

public class Main {
    public static void main(String[] args) {
        Adder adder = (x, y) -> x + y;
        
        System.out.println(adder.add(5, 3));  // 출력: 8
    }
}

List 예제

  1. 기본 익명 클래스 사용:
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry");

        Consumer<String> consumer = new Consumer<String>() {    //익명의 내부 클래스로 구현
            @Override
            public void accept(String s) {
                System.out.print(s + " ");
            }
        };
        list.forEach(consumer);
    }
}

  1. 람다식 사용:
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<String> list = Arrays.asList("apple", "banana", "cherry");

        list.forEach( s -> System.out.print( s + " "));
        //출력 : apple banana cherry
        list.forEach(System.out::print);
        //출력 : applebananacherry
        //메서드 참조는 문자열을 포맷팅하거나 추가적인 처리를 직접적으로 할 수 없다
    }
}

두개 이상의 매개변수 예제

1. BiFunction 예제

BiFunction<T, U, R> 인터페이스는 두 개의 매개변수(T, U)를 받고 결과(R)를 반환하는 함수형 인터페이스입니다.

예를 들어, 두 정수를 더하는 람다식을 작성할 수 있습니다.

import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
    
        // 두 개의 Integer를 받아서 Integer를 반환하는 BiFunction
        //BiFunction<Integer, Integer, Integer> add = (x, y) -> x + y;
        BiFunction<Integer, Integer, Integer> add = Integer::sum;

        // 함수 호출
        System.out.println("Sum: " + add.apply(5, 3)); // 출력: Sum: 8
    }
}

2.1 BiConsumer 예제 1

BiConsumer<T, U> 인터페이스는 두 개의 매개변수를 받아 아무 결과도 반환하지 않는 함수형 인터페이스입니다.

예를 들어, 두 문자열을 합쳐서 출력하는 람다식을 작성할 수 있습니다.

import java.util.function.BiConsumer;

public class Main {
    public static void main(String[] args) {
        // 두 개의 String을 받아서 콘솔에 출력하는 BiConsumer
        BiConsumer<String, String> printConcatenation = (s1, s2) -> System.out.println(s1 + s2);
        
        // 함수 호출
        printConcatenation.accept("Hello, ", "World!"); // 출력: Hello, World!
        
        ////////////////////////////////////////////////////////////////////////////////////////////////
        //메서드 참조는 문자열을 포맷팅하거나 추가적인 처리를 직접적으로 할 수 없다.
        //그래도 하려면 아래 코드
        Consumer<String> print = System.out::println;
        
        
        String s1 = "Hello, ";
        String s2 = "World!";
        print.accept(s1 + s2); // 출력: Hello, World!
    }
}

2.1 BiConsumer 예제 2

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;

public class Main {
    public static void main(String[] args) {
        // Map 생성 및 데이터 추가
        Map<String, String> map = new HashMap<>();
        map.put("a", "ant");
        map.put("b", "bee");
        map.put("c", "cow");

        // BiConsumer를 사용하여 Map의 키와 값을 출력
        BiConsumer<String, String> printEntry = (key, value) -> 
		        System.out.println("Key: " + key + ", Value: " + value);
		        
        map.forEach(printEntry);
        
        
        //더 간결한 람다식
        map.forEach((key, value) -> System.out.println("Key: " + key + ", Value: " + value));

        });
    }
}

 

공부할때 List의 타입을 Object 로 두고 테스트를 진행했지만, 람다식을 사용할때는 타입에 관계없이 타입에 따라

람다식의 매개변수 타입이 자동으로 추론됩니다.

가장 일반적인 함수형 인터페이스는 Runnable, Callable, Consumer, Supplier, Function, Predicate 등이 있습니다.

 

그 외 함수 https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html

'Java' 카테고리의 다른 글

JDBC 정리  (0) 2024.08.02
JDBC  (0) 2024.08.01
클래스 형변환  (0) 2024.07.24
static  (0) 2024.07.21
this  (0) 2024.07.19