[기술정리] 람다식(Lamda)

이나겸's avatar
Nov 25, 2024
[기술정리] 람다식(Lamda)

💡

람다식(람다 표현식)

프로그래밍에서 익명 함수 (이름 없는 함수)를 나타내는 간결한 방식 (Java 8부터 도입)
짧은 코드 블록을 표현하거나 일회성으로 사용되는 함수의 정의를 간단히 할 때 사용
코드가 더 간결하고 명확해짐

특징

  • 익명 클래스에 비해 훨씬 간단하게 작성 가능해서 코드가 간결해짐
  • 복잡한 코드가 단순화돼서 가독성 향상
  • 일회성으로 사용되는 함수 정의를 간단히 처리 가능
  • 다른 함수의 매개 변수로 전달하기 용이
  • 다양한 상황에서 유연한 활용 가능
    • 특히 컬렉션과 스트림 API를 사용할 때 유용

제약

  • 함수형 인터페이스만 지원
    • 추상 메서드가 2개 이상인 인터페이스에는 사용 불가
  • 디버깅 어려움
    • 복잡한 람다식은 디버깅이 까다로울 수 있음
  • 가독성 문제
    • 너무 긴 람다식 사용하면 오히려 가독성 떨어질 수 있음

람다는 인터페이스로 만듦

  • 함수형 인터페이스를 구현하기 위해 사용
  • 함수형 인터페이스는 하나의 추상 메서드만 가지는 인터페이스로 정의됨

인터페이스에서는 메서드가 하나만 존재해야 함

  • 하나의 추상 메서드만 가지는 함수형 인터페이스를 구현
  • 하지만 하나의 추상 메서드 외에도 여러 개의 디폴트 메서드나 정적 메서드를 가질 수 있음

메서드가 인터페이스를 매개 변수로 받고 있으면, 행위를 줘야함

  • 함수형 인터페이스를 매개 변수로 받는 메서드는 실제로 특정 동작이나 행위를 전달하는 의미로 사용
  • 높은 수준의 추상화를 통해 행위를 메서드에 전달하는 방식

람다에서는 매개 변수에 타입 생략 가능

  • ( ) → { }
    • (매개 변수) → {실행 코드}
    • 매개 변수 : 함수의 입력 값
    • → : 매개 변수와 함수 본체를 구분하는 화살표
    • 실행 코드 : 람다식의 본체, 함수의 동작을 정의
  • 매개 변수 타입 생략 가능
    • 괄호를 해도 되고 안 해도 되는데 값(매개 변수)이 없으면 괄호 있어야 함
    • 컴파일러는 람다식의 문맥으로부터 타입을 추론할 수 있음
// 매개 변수 타입 생략 안 함 => 괄호 존재 MyConsumer<Integer> consumer = (data) -> { System.out.println(data); }; // 매개 변수 타입 생략 => 괄호 생략 MyConsumer<Integer> consumer = data -> { System.out.println(data); };

@FunctionalInterface(런타임 실행) 표시 가능

  • 함수형 인터페이스로 명시
    • @FunctionalInterface 어노테이션으로 해당 인터페이스가 함수형 인터페이스임을 명시적으로 선언 가능
  • 컴파일러 체크
    • 인터페이스에 추상 메서드가 두 개 이상 존재할 경우 컴파일 오류 발생시켜서 함수형 인터페이스의 규칙 위반하지 않도록 함

종류

MyConsumer<T>

  • 입력만 받고 출력이 없는 연산 수행
// 입력만 받고 출력이 없는 연산 수행 @FunctionalInterface public interface MyConsumer<T> { void accept(T data); }

MySupplier<T>

  • 입력 없이 값 반환(return)
// 입력 없이 값을 반환(return) => 공급자 // 입력이 없으니 매개변수도 없음 => 반환은 해야하니까 generic(T) 필요 @FunctionalInterface public interface MySupplier<T> { T get(); }

MyFunction<T, R>

  • 입력을 받아서 결과 반환(return)
// 입력을 받아서 결과를 반환 // 입력과 결과 다 필요하니까 generic 2개 @FunctionalInterface public interface MyFunction<T,R> { R apply(T t); }

MyPredicate<T>

  • 입력을 받아서 논리값(boolean) 반환(return)
// 입력을 받아 논리값(boolean)을 반환 // generic(T)(boolean) 반환 @FunctionalInterface public interface MyPredicate<T> { boolean test(T t); }

종류 별 활용 및 실행 결과

// 1. 람다는 인터페이스로 만듦 // 2. 인터페이스에서는 메소드가 하나만 존재해야 함 // 3. 메소드가 인터페이스를 매개변수로 받고 있으면, 행위를 주세요!! // 4. 람다에서는 매개변수에 타입을 생략 가능 // 5. @FunctionalInterface(런타임 실행) 표시 가능 public class App { public static void main(String[] args) { // 람다식 : () -> {} // 4-1. ()안은 매개변수인데 괄호를 해도 되고 안해도 되고 // 물론 값(매개변수)이 없으면 괄호 있어야함 MyConsumer<Integer> r1 = (data) -> { System.out.println("소비할 데이터 : " + data); }; r1.accept(1); // 소비할 데이터 : 1 출력 // good 문자열 반환하는 람다식 // 람다표현식 : 표현식은 무조건 반환(return)이 됨 MySupplier<String> r2 = () -> { return "good"; }; // 람다식은 중괄호와 return을 생략해도 자동 반환(return)이 됨 MySupplier<String> r3 = () -> "good"; System.out.println(r2.get() + "/" + r3.get()); // good / good 출력 // 받은 문자열의 길이값을 반환하는 람다식 MyFunction<String, Integer> r4 = (String s) -> s.length(); System.out.println("Length of 'hello': " + r4.apply("hello")); // Length of 'hello': 5 출력 // 숫자가 짝수인지 확인하는 람다식 MyPredicate<Integer> r5 = (Integer x) -> x % 2 == 0; System.out.println(r5.apply(3)); // false 출력 } }
notion image
Share article

Nakyeom's Study