람다

WAS·2026년 2월 6일

람다 특징

  • 람다 는 익명함수를 지칭하는 일반적인 용어 = 이름 없이 함수 표현
  • 람다식 은 (매개변수) -> {본문} 형태로 람다를 구현하는 구체적인 문법 표현을 지칭
  • 람다 를 사용할 때 new 키워드를 사용하지 않지만, 인스턴스가 생성된다
  • 람다 를 사용하면 표현이 간결하다
  • 람다 는 변수처럼 다룰 수 있다
  • 대부분의 익명 클래스람다 로 대체할 수 있다
    참고로 람다익명 클래스 를 완전히 대체할 수 있는 것은 아님
반환타입 메서드명(매개변수) { // 일반 함수 표현식
 	본문
}

public int add(int x){
	return x + 1;
}

(매개변수) -> {본문} // 람다 표현식
(int x) -> {return x + 1;}

람다 사용방법 : 함수명, 반환 타입은 생략하고 매개변수와 본문만 간단하게 적으면 됨


함수형 인터페이스

  • 딱 하나의 추상 메서드를 가지는 인터페이스
  • 람다 는 추상 메서드가 하나인 인터페이스에만 할당할 수 있음
  • 단일 추상 메서드를 줄여서 SAM (Single Abstract Method) 라고 부름
  • 람다는 클래스나 추상클래스에 할당할 수 없으며, 단일 추상 메서드를 가지는 인터페이스에만 할당할 수 있음
public interface NotSamInterface {
	void run(); // 메서드 앞에는 abstract 키워드가 생략되있음
    void go();
    // 여기서는 두개의 추상 메서드가 선언되 있으므로, 단일 추상메소드가 아니다
    // 그래서 이 인터페이스에는 람다를 할당할 수 없다
}

왜 위의 코드에서 람다 를 할당할 수 없을까?
-> 람다는 하나의 함수라서, 람다를 인터페이스에 담으려면 하나의 메서드 선언만 존재해야함
-> 두개 이상이면 어떤 메서드에 할당해야하는지 알 수 없기 때문에 컴파일 오류 발생

인터페이스에 하나의 추상 메서드만 사용한다라고 표현하려면 @FunctionalInterface 를 사용
@FunctionalInterface : 함수형 인터페이스 임을 선언
이 어노테이션을 사용하면 누군가 실수로 추상 메서드를 추가하면 컴파일 오류가 발생

따라서 람다를 사용할 함수형 인터페이스 라면 @FunctionalInterface 필수로 추가 권장


✅ 람다와 생략

예제 (1)

@FunctionalInterface 
public interface MyFunction { // MyFunction 인터페이스
 	int apply(int a, int b);
}

MyFunction 인터페이스를 재정의하면 다음과 같이 표현할 수 있다

MyFunction function1 = (int a, int b) -> {
 	return a + b;
};

위 function1 처럼 단일표현식 인 경우 중괄호와 리턴을 생략할 수 있다

MyFunction myFunction2 = (int a, int b) -> a + b;

하지만 여러문장이 있으면 (단일표현식) 이 아닌 경우는 생략하면 안된다

MyFunction myFunction3 = (int a, int b) ->{
	System.out.println("hi");
	return a + b;
};

함수형 인터페이스에 이미 int 형으로 정의되어 있으므로, 매개변수 타입을 생략할 수 있다

MyFunction myFunction4 = (a,b) -> a + b;

만약에 매개변수가 딱 하나라면 () 를 생략할 수 있다 (매개변수 없거나, 두개 이상이면 안됨)

MyFunction myFunction5 = a -> a * 2;

다음은 Procedure 인터페이스의 예시를 보여주겠다

public interface Procedure {
	 void run();
}

위 문장을 재정의하면 다음과 같이 표현할 수 있다

Procedure procedure = () ->{
	System.out.println("hi");
};

하지만 위 문장은 단일표현식 이므로 중괄호를 생략할 수 있다

Procedure procedure2 = () -> System.out.println("hi");

✅ 람다의 전달

  • 람다를 변수에 대입할 수 있음

람다도 인터페이스를 사용하므로, 람다 인스턴스 참조값을 변수에 전달할 수 있다

MyFunction add = (a,b) -> a+b;
MyFunction sub = (a,b) -> a-b;
System.out.println(add.apply(2,3)); // 5
System.out.println(sub.apply(2,3)); // -1

// 변수를 통해 전달
MyFunction cal = add; // 람다를 변수에 대입
System.out.println(cal.apply(2,3)); // 5

// 람다를 직접 전달
calculate((a,b) -> a + b);
calculate((a,b) -> a - b);

static void calculate(MyFunction function) {
	int a = 1;
	int b = 2;
		
	int result = function.apply(a, b);
	System.out.println(result);	
}

또 람다를 반환할 수 도 있다

public static void main(String[] args) {
 MyFunction add = getOperation("add"); 
 System.out.println(add.apply(1, 2)); // 3
 
 MyFunction sub = getOperation("sub");
 System.out.println(sub.apply(1, 2)); // -1
 
 MyFunction xxx = getOperation("xxx");
 System.out.println(xxx.apply(1, 2)); // 0
 }
 
 // 람다를 반환하는 메서드
 static MyFunction getOperation(String operator) {
     switch (operator) {
       case "add":
       return (a, b) -> a + b;
       case "sub":
       return (a, b) -> a - b;
       default:
       return (a, b) -> 0;
	 }
 }

고차함수

  • 함수를 값처럼 다루는 함수를 의미함

다음 2가지 중 하나를 만족하면 고차 함수 라고 한다

  • 함수를 인자로 받는 함수
  • 함수를 반환하는 함수
static void calculate(MyFunction function) { // 함수(람다)를 인자로 받는 경우
 	// ...
 }
 
static MyFunction getOperation(String operator) { // 함수(람다)를 반환하는 경우
 	// ...	
	return (a, b) -> a + b;
}

보통의 일반 함수들은 인수로 값을 받고, 값을 반환한다
하지만 고차함수는 함수로 인자를 받거나 함수를 반환한다
고차함수는 함수라는 개념 자체를 값처럼 다룬다는 점에서 추상화 의 수준(계층)이
한 단계 높아진다고 해서 고차함수 라고 한다


✅ 함수형 인터페이스에 제네릭 도입

@FunctionalInterface
interface GenericFunction<T, R> {
	R apply(T s); // T : 매개변수 타입  R : 반환 타입
}
GenericFunction<String, String> toUpperCase = str -> str.toUpperCase();
GenericFunction<String, Integer> stringLength = str -> str.length();
GenericFunction<Integer, Integer> square = x -> x * x;
GenericFunction<Integer, Boolean> isEven = num -> num % 2 == 0;

	System.out.println(toUpperCase.apply("hello")); // HELLO
	System.out.println(stringLength.apply("hello")); // 5
	System.out.println(square.apply(3)); // 9
	System.out.println(isEven.apply(3)) // false

제네릭을 사용하면 동일한 구조의 함수형 인터페이스를 다양한 타입에 재사용할 수 있다
제레닉을 넣음으로써, apply() 의 매개변수와 반환 타입을 유연할게 할 수 있다
위에서 선언한 GenericFunction() 은 매개변수가 1개고, 반환값이 있는 모든 람다에 사용 가능

💡 하지만 람다르 사용하려면 함수형 인터페이스가 필수이기 때문에,


profile
우측 상단 햇님모양 클릭하셔서 무조건 야간모드로 봐주세요!!

0개의 댓글