Java (람다식 Lambda Expression)

최병현·2026년 1월 15일

Java

목록 보기
38/38

이번 글은 Backend / OOP logic in Java 영역에서 매우 자주 사용되는 Lambda Expression(람다식)을 정리한다. 람다는 단순히 “짧게 쓰는 문법”이 아니라, 메서드(동작)를 하나의 식(Expression)으로 표현하여 값처럼 전달하기 위한 자바의 핵심 문법이다.

Java 8부터 도입된 함수형 프로그래밍 스타일로, 기존 Java에서 반드시 필요했던 클래스 정의 + 객체 생성 + 메서드 구현 과정을 크게 줄여준다. 원래 개념적으로는 익명 함수(Anonymous Function)라고 부르며, Java에서는 함수형 인터페이스와 함께 사용된다.


1. 람다식이란?

람다식은 익명 클래스(Anonymous Class)를 더 간결하게 표현한 문법이다. 즉, “이름 없는 구현 객체를 즉석에서 만들어서 전달한다”는 개념은 동일하고, 표현 방식만 간단해진 것이다.

  • 익명 클래스: 클래스 구조로 구현 → 코드가 길어짐
  • 람다식: 메서드(동작)만 표현 → 코드가 매우 짧아짐

이를 통해 자바 코드는 “객체 중심”에서 “동작 중심”으로 더 유연한 구조를 가질 수 있다.


2. 람다식의 전제 조건: 함수형 인터페이스

람다식은 아무 곳에서나 사용할 수 있는 문법이 아니다. 반드시 추상 메서드가 정확히 1개인 인터페이스에서만 사용 가능하다. 이러한 인터페이스를 함수형 인터페이스(Functional Interface)라고 부른다.

자바에서는 @FunctionalInterface 애노테이션을 통해 이를 강제할 수 있으며, 추상 메서드가 2개 이상이면 컴파일 에러가 발생한다.

3. 람다식 문법 구조

기존 메서드에서 메서드명과 반환 타입을 제거하고, -> 기호를 사용해 표현한다.

기본 구조는 다음과 같다.

(매개변수) -> { 실행문 }

  • 메서드 이름 제거
  • return 타입 제거
  • 동작만 표현

4. 기존 방식 vs 람다식

두 수를 비교하는 Comparator를 기존 방식(익명 클래스)으로 작성하면 다음과 같다.

Comparator<Integer> comp = new Comparator<>() {
    @Override
    public int compare(Integer a, Integer b) {
        return a.compareTo(b);
    }
};

람다식으로 바꾸면 훨씬 간결해진다.

Comparator<Integer> comp = (a, b) -> a.compareTo(b);

즉, 람다는 “익명 클래스의 메서드 구현부만 남긴 형태”라고 이해하면 된다.


5. 람다식을 사용하는 이유

1) 코드 간결성

클래스 선언, 메서드 선언 등 불필요한 구조가 사라지고, 핵심 동작만 표현할 수 있다.

2) 컬렉션(Collection) 활용 극대화

람다는 Stream API와 결합될 때 가장 강력하다. 반복문과 조건문을 대폭 줄일 수 있다.

3) 병렬 처리에 유리

람다 기반 Stream 구조는 내부적으로 멀티코어 환경에서 병렬 처리(parallel processing)를 쉽게 확장할 수 있는 구조를 제공한다.


6. Stream API + 람다 예제 (짝수 필터링)

기존 반복문 방식은 다음과 같다.

List<Integer> nums = List.of(1,2,3,4,5,6,7,8,9,10);
List<Integer> evenNums = new ArrayList<>();

for (Integer num : nums) {
    if(num % 2 == 0) evenNums.add(num);
}
System.out.println(evenNums);

Stream API와 람다식을 활용하면 다음과 같이 표현할 수 있다.

nums.stream()
    .filter(n -> n % 2 == 0)
    .forEach(System.out::println);

반복문과 조건문이 사라지고, “무엇을 할 것인지”가 코드에 직접 드러난다.


7. 람다식 문법 생략 규칙

  • 매개변수 타입 생략 가능: (int a) → (a)
  • 매개변수가 1개면 괄호 생략 가능: (a) → a
  • 실행문이 한 줄이면 {}와 return 생략 가능
a -> { return a * a; }   // 원래 형태
a -> a * a              // 생략 형태

8. 자주 사용되는 Stream API

1) filter

특정 조건에 맞는 데이터만 선택한다. 데이터 개수는 줄어들 수 있지만, 타입은 유지된다.

2) map

데이터를 다른 값이나 형태로 변환한다. 데이터 개수는 유지되지만, 값이나 타입이 변경될 수 있다.

3) sorted

정렬 기준에 따라 순서를 변경한다. 데이터 내용과 개수는 변하지 않는다.

List<Integer> scores = List.of(23,1657,2654,9403,59,68,1,5,67,4,3,56);

scores.stream()
      .filter(s -> s >= 60)
      .map(s -> s + 5)
      .sorted()
      .forEach(System.out::println);

9. 사용자 정의 함수형 인터페이스 활용

@FunctionalInterface
public interface Calculator {
    int compute(int a, int b);
}

public class CalculatorMain {

    public static int operate(int a, int b, Calculator c) {
        return c.compute(a, b);
    }

    public static void main(String[] args) {

        Calculator add = (x, y) -> x + y;
        Calculator sub = (x, y) -> x - y;
        Calculator mul = (x, y) -> x * y;
        Calculator div = (x, y) -> x / y;

        System.out.println("2 + 3 = " + operate(2, 3, add));
        System.out.println(sub.compute(3, 4));
        System.out.println(operate(4, 5, mul));
    }
}

람다식은 결국 인터페이스의 추상 메서드 1개를 구현한 객체이며, 메서드를 값처럼 전달할 수 있게 만든 구조다.


10. forEach + 람다 예제

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

public class ForEachMain {
    public static void main(String[] args) {
        List<String> fruits = Arrays.asList("사과", "딸기", "블루베리");

        fruits.forEach(fruit -> System.out.println("과일명: " + fruit));

        System.out.println();

        List<Integer> nums = List.of(1,2,3,4,5);
        nums.forEach(num -> System.out.print((num * 2) + " "));
    }
}

forEach()는 원본 컬렉션을 변경하지 않고, 각 요소에 대해 동작만 적용한다.


11. 정리

  • 람다식은 익명 클래스의 구현부를 간결하게 표현한 문법이다.
  • 람다는 함수형 인터페이스(추상 메서드 1개)에서만 사용 가능하다.
  • Stream API와 결합하면 컬렉션 처리 코드가 매우 간결해진다.
  • 정책/전략 로직을 동작 단위로 전달할 수 있어 확장성과 가독성이 좋아진다.

12. 느낀 점

람다식을 단순히 “코드를 줄이는 문법”으로 보면 절반만 이해한 것이다. 실제로는 OOP 구조(인터페이스 기반 다형성)를 유지하면서도 동작을 유연하게 주입할 수 있게 만든 강력한 도구다. 특히 계산 로직, 검증 정책, 정렬 기준처럼 “상황에 따라 바뀌는 동작”을 표현할 때 람다는 자바 코드를 훨씬 읽기 쉽게 만들어준다.

profile
No Pain No Gain

0개의 댓글