본문 바로가기

DEV_BACKEND/Java

[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 부트캠프 13기: Java 39일차 람다식

1. 람다식(Lambda Expression)

람다식은 익명 함수(Anonymous Function) 를 작성하는 간결한 방법으로, Java 8부터 도입되었습니다. 이를 활용하면 코드가 더 간결해지고 가독성이 향상됩니다.

 

기본 문법 : (매개변수) -> { 실행 코드 }

예제: 기존 방식과 비교

(1) 익명 클래스 방식

// Runnable 인터페이스를 익명 클래스로 구현
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello, World!");
    }
};

 

(2) 람다식 사용

Runnable runnable = () -> System.out.println("Hello, World!");

 

➡ 람다식을 사용하면 코드가 훨씬 간결해집니다.

 

람다식 활용 예제

// (1) 매개변수 O, 리턴 O
// 두 숫자를 더하는 람다식
BiFunction<Integer, Integer, Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(10, 20)); // 출력: 30

// (2) 매개변수 O, 리턴 X
// 문자열을 출력하는 람다식
Consumer<String> print = s -> System.out.println(s);
print.accept("Hello, Lambda!"); // 출력: Hello, Lambda!

// (3) 매개변수 X, 리턴 O
// 랜덤 숫자를 반환하는 람다식
Supplier<Double> random = () -> Math.random();
System.out.println(random.get()); // 0.123456789 같은 랜덤 값 출력

// (4) 매개변수 X, 리턴 X
// 실행만 하는 람다식
Runnable hello = () -> System.out.println("Hello!");
hello.run(); // 출력: Hello!

 

1.2 람다식의 정의와 이론적 기초

람다식이란, 간단히 말해 익명 함수의 일종입니다. 이는 이름이 없는 함수를 정의하는 방법으로, 빠르고 간결한 함수 작성을 가능하게 합니다. 자바에서 람다식은 자바 8부터 도 입되었으며, 이를 통해 함수형 프로그래밍의 개념이 객체 지향 프로그래밍 언어에 통합 되었습니다.

 

1. 매개변수 리스트: 함수가 받아들이는 매개변수들의 목록입니다. 예를 들어, (a, b) 는 두 개의 매개변수를 받아들입니다. 2. 화살표(->) 기호: 매개변수와 람다 몸체를 구분하는 기호입니다.

3. 람다 몸체: 실제 람다식의 실행 부분으로, 함수의 몸체와 유사합니다. 이 부분에서는 매개변수를 사용하여 특정 작업을 수행하고 결과를 반환할 수 있습니다.

 

람다식의 특징

익명성: 람다식은 이름이 없기 때문에 익명으로 사용됩니다. 이는 코드의 간결성을 높이고, 재사용성을 감소시킵니다.

함수형 인터페이스와의 연결: 람다식은 함수형 인터페이스의 구현체로 사용됩니다. 함수형 인터페이스는 오직 하나의 추상 메소드를 가진 인터페이스로, 람다식을 통해 간결하게 표현할 수 있습니다.

간결성과 표현력: 람다식은 코드를 간결하게 만들고, 명확한 표현을 가능하게 합니 다. 이를 통해 개발자는 보다 직관적이고 간단한 코드 작성에 집중할 수 있습니다.

 

 

그래서.. 언제, 왜 사용하는데?

결론: 람다는 "간결한 코드"와 "일회성 사용"이 필요한 경우에 사용!

💡 언제 쓰면 좋을까?콜백 함수 처리할 때 (이벤트 핸들러 등)
반복문을 간소화하고 싶을 때 (forEach(), stream() 등)
데이터 필터링/가공할 때 (filter(), map(), reduce() 등)
간단한 비교, 정렬 로직이 필요할 때 (Comparator, sort())

🚨 하지만 코드가 너무 길거나 복잡해지면 메서드로 분리하는 게 더 좋음!

 

 

📌 람다 함수를 사용하면 좋은 상황

1. 불필요한 익명 클래스를 줄이고 싶을 때

✅ 기존 방식 (익명 클래스 사용)

List<String> names = List.of("Alice", "Bob", "Charlie");

Collections.sort(names, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

 

✅ 람다식 사용

Collections.sort(names, (s1, s2) -> s1.length() - s2.length());

👉 코드가 훨씬 짧고 가독성이 좋아짐


2. 콜백 함수를 간결하게 표현할 때

✅ 기존 방식 (익명 클래스)

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        System.out.println("버튼 클릭됨");
    }
});

 

✅ 람다식 사용

button.setOnClickListener(v -> System.out.println("버튼 클릭됨"));

👉 일회성 이벤트 처리 코드가 간결해짐


3. 컬렉션(리스트, 맵 등) 데이터를 간결하게 처리할 때

✅ 기존 방식 (for문 사용)

List<String> names = List.of("Alice", "Bob", "Charlie");

for (String name : names) {
    System.out.println(name);
}

 

✅ 람다식 사용 (forEach)

names.forEach(name -> System.out.println(name));

👉 코드가 직관적이고 간결해짐


4. 스트림 API와 함께 사용할 때

✅ 기존 방식 (반복문 사용)

List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = new ArrayList<>();

for (int num : numbers) {
    squaredNumbers.add(num * num);
}
System.out.println(squaredNumbers); // [1, 4, 9, 16, 25]

 

✅ 람다식 + 스트림 사용

List<Integer> squaredNumbers = numbers.stream()
    .map(n -> n * n)
    .collect(Collectors.toList());

System.out.println(squaredNumbers); // [1, 4, 9, 16, 25]

👉 데이터 가공을 훨씬 깔끔하게 처리 가능


5. 특정 조건에 맞는 데이터 필터링할 때

✅ 기존 방식 (for문 사용)

List<String> names = List.of("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = new ArrayList<>();

for (String name : names) {
    if (name.startsWith("C")) {
        filteredNames.add(name);
    }
}

System.out.println(filteredNames); // [Charlie]

 

✅ 람다식 + 스트림 사용

List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("C"))
    .collect(Collectors.toList());

System.out.println(filteredNames); // [Charlie]

👉 데이터 필터링을 더 직관적으로 표현 가능


📢 람다 함수를 사용하기 적합하지 않은 경우

  1. 로직이 복잡할 때
    → 람다식이 너무 길어지면 오히려 가독성이 떨어짐. 이럴 땐 메서드로 분리하는 것이 좋음.
  2. 상태를 변경해야 할 때
    → 람다는 기본적으로 불변(immutable)한 처리에 적합함. 변수 값을 변경해야 하는 경우 일반 메서드가 더 적절할 수 있음.
  3. 재사용성이 필요한 경우
    → 람다는 익명 함수라서 반복적으로 사용할 필요가 있는 경우 일반적인 메서드로 구현하는 것이 좋음.

 

정리

  • 람다식: 익명 함수를 간단하게 표현하는 문법 ( (x) -> { 실행 코드 } )
  • 스트림: 컬렉션 데이터를 효율적으로 처리하는 API ( .stream() 사용)