Dev/Java

[Java] Lambda

syuare 2025. 4. 25. 20:32

Lambda가 무엇인가?

익명 클래스를 더 간결하게 표현하는 문법

익명의 함수를 정의하고 직접 전달하고 실행할 수 있는 방식

더보기

익명 클래스

  • 이름이 없는 클래스
  • 별도의 클래스 파일을 만들지 않고 코드 내에서 일회성으로 정의해 사용하기 때문
  • 인터페이스나 클래스의 구현, 상속을 활용해서 구현할 수 있다
// 익명 클래스란?
public interface Calculator {
    int sum(int a, int b);
}


/* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */

public class Main {
	public static void main(String[] args) {
		// 익명 클래스 활용
		Calculator calculator1 = new Calculator() {
        	@Override
			public int sum(int a, int b) { return a + b; }
		};
        
		int ret1 = calculator1.sum(1, 1);
		System.out.println("ret1 = " + ret1); // 2
    }
}

Java - Lambda는 함수형 인터페이스 사용을 적극 권장 (권장이지만, 필수는 아니다.)

  • 함수형 인터페이스는 하나의 추상 메서드만 가진 인터페이스이기 때문
    • Calculator 인터페이스에 추상 메서드가 하나뿐이기 때문에
    • 컴파일러는 (a, b) -> a + b 람다 표현식이 sum() 메서드라고 추론하여 구현한다. 
      •  Lambda는 익명 클래스를 만들어줘야 하는데, 추상 메서드가 여러 개이면 어떤 메서드를 구현해야할지 판단하기 어렵게 됨
@FunctionalInterface // 함수형 인터페이스 명령어
public interface Calculator {
	int sum(int a, int b);
}

Lambda식 표현

람다 표현식은 보통 하나의 매개변수를 받아 하나의 결과를 반환하는 간단한 함수이다.

(매개변수들) -> { 실행할 코드 }

// 매개변수(Parameters) 함수에 사용하는 입력 값들 > 매개변수가 하나면 괄호 생략 가능
// 화살표(->): 매개변수와 실행 코드 블록을 구분
// 실행 코드: Lambda에서 실행하는 로직
              코드를 여러 줄 작성 가능(중괄호 사용)
// (a, b) -> a + b
// a, b: 매개변수
// a + b: 실행할 코드
BinaryOperator<Integer> add = (a, b) -> a + b;
System.out.println(add.apply(5, 3));  // 출력: 8

// (str) -> str.length()
Function<String, Integer> stringLength = str -> str.length();
System.out.println(stringLength.apply("Hello"));  // 출력: 5
더보기
// Lambda식 표현
Calculator calculator2 = (a,b) -> a + b;


// 아래의 클래스를 내부적으로 자동으로 만든다
// Calculator 클래스 존재X > 익명클래스
Calculator calculator = new Calculator() { 
	@Override
	public int sum(int a, int b) {
	return a + b;
	}
};



@FunctionalInterface
public interface Calculator {

    int sum(int a, int b);
}

Lambda 표현식 사용하는 이유

  • 간결한 코드 작성
    • 익명 클래스보다 더 간단한 방식으로 함수형 인터페이스를 구현 가능
    • 코드 간결화로 읽기 쉽고 유지보수도 편리합니다.
  • 함수형 프로그래밍 지원
    • 함수형 프로그래밍을 가능하게 하여 컬렉션 처리 등을 훨씬 더 깔끔하게 작성 가능
    • 함수(메서드)를 인자로 전달하거나 반환값으로 사용할 수 있습니다.
  • 병렬 처리와 스트림
    • 람다 표현식은 스트림 API와 함께 사용하면 병렬 처리(parallel processing)나 데이터 처리 작업을 더욱 간편하게 구현
    • Stream과 함께 사용하면 데이터를 더 쉽고 효율적으로 처리할 수 있습니다.
더보기
// 1. 데이터 준비: 스트림 생성
Stream<Integer> stream = arrayList.stream();
// 2. 중간 연산 등록: 각 요소를 10배로 변환 로직 등록
Stream<Integer> mappedStream = stream.map(num -> num * 10);
// 3. 최종 연산: 최종 결과 리스트로 변환
List<Integer> ret2 = mappedStream.collect(Collectors.toList());

// 위의 1~3줄의 코드를 한 줄로 표현 가능
List<Integer> ret2 = arrayList.stream() // 1. 데이터 준비
    .map(num -> num * 10)               // 2. 중간 연산 등록
    .collect(Collectors.toList());  // 3. 최종 연산



// 익명 클래스
Button button = new Button();
button.setOnClickListener(new OnClickListener() {
    public void onClick(View v) {
        System.out.println("버튼 클릭됨!");
    }
});

// Lambda식 표현
Button button = new Button();
button.setOnClickListener(v -> System.out.println("버튼 클릭됨!"));

Lambda 주의사항

람다는 익명 클래스의 간소화 버전이므로, 람다 표현식을 과도하게 사용하면 코드가 지나치게 복잡해질 수 있다.