[Java] 람다(Lambda)

박채은·2022년 11월 14일
0

Java

목록 보기
23/30

람다식

  • 함수형 프로그래밍 기법을 지원하는 자바 문법
  • 메서드를 간단하게 만들기 위한 방법(메서드를 하나의 식으로 표현)
  • 자바는 객체지향 프로그래밍 언어이지만 람다식의 함수형 프로그래밍 문법 요소를 도입하여 객체지향과 함수형을 혼합한 방식을 사용한다.
  • Stream에 사용 가능

객체지향적 언어인 자바의 특성에 따라, 람다식은 일반적인 함수가 아니라 익명 객체이다.

-> 자바는 객체지향 언어이므로 모든 메서드는 클래스 내부에 있어야 하고, 람다식은 메서드이므로 익명 클래스 내부에 있어야 한다.
-> 하지만 기존의 익명 클래스처럼 사용하게 된다면, 람다식의 간편함을 사용하지 못한다.
-> 따라서 기존 자바의 객체 지향 문법 요소를 해치지 않고, 함수형 프로그래밍 기법을 사용할 수 있는 장치인 "함수형 인터페이스"가 만들어졌다.


문법

  • 함수의 반환 타입, 이름 생략(=> 익명 함수라고도 부른다.)
  • 화살표 추가
  • 매개변수의 타입 생략 가능
  • 실행문이 한 줄인 경우에, 중괄호 생략 가능

익명 클래스/객체

객체의 생성과 선언이 동시에 일어나는 클래스/객체
= 일회성 클래스/객체
= 한번 만들어지고, 한번 사용되는 클래스/객체


함수는 반드시 클래스 안에서 정의되어야 하기 때문에 메서드가 독립적으로 있을 수 없고 반드시 클래스 객체를 먼저 생성한 후 생성한 객체로 메서드를 호출해야 합니다.

그러므로 위에서 말했던 것과 같이, 람다식 또한 하나의 익명 클래스이다.

// sum 메서드의 람다식 
(num1, num2) -> num1+num2;

// 실제 람다식 - 익명 클래스 내부에 메서드가 존재하는 형태
new Object(){
	int sum(int num1, int num2){
    	return num1+num2;
    }
}

람다식의 실제 모습은 익명 클래스이고, 그 내부의 메서드를 사용하기 위해서는 결국 참조 변수가 필요하다.

Object obj = new Object(){
	int sum(int num1, int num2){
    	return num1+num2;
    }
}
obj.sum(4,5);

참조 변수를 통해서, 익명 클래스 내부에 있던 메서드를 사용할 수 있다.

하지만 이것을 람다식으로 또 바꿔보자.

Object obj = (num1, num2) -> num1+num2;
obj.sum(4,5); // 오류 발생

람다식으로 바꾸면, 오류가 발생한다.
코드에서 보이는 것처럼, Object 클래스에는 sum 메소드가 없기 때문에 호출을 할 수 없다.

람다식으로 바꿨을 때, 메서드를 사용할 수 없는 문제를 해결하기 위해서, 만들어진 것이 "함수형 인터페이스"이다.

람다식도 결국 하나의 객체이기 때문에 인터페이스에 정의된 추상 메서드를 구현할 수 있다.


함수형 인터페이스

  • 단 하나의 추상 메서드만 존재
  • 그 이유는?
    -> 람다식과 메서드가 1:1로 매칭되어야 하므로

함수형 인터페이스를 사용할 때, 우리는 직접 인터페이스를 선언했다.
하지만 매번 비슷한 것들을 선언하는 것은 귀찮기 때문에 자주 사용하는 함수형 인터페이스가 패키지에 선언되어 있다.
이것을 우리는 사용하기만 하면 된다!

공식 문서
참고 블로그

  • Runnable: 인풋, 아웃풋 모두 없는 void의 경우
  • Supplier : 인풋은 없고, 아웃풋만 있는
  • Consumer : 인풋은 있고, 아웃풋은 없는

또한, 람다도 객체이니까 함수에서 객체를 리턴할 수 있고, 매개변수로 객체를 전달할 수 있는 것처럼 람다도 리턴할 수 있고, 매개변수로 전달해줄 수 있다.
람다식을 변수처럼 활용하는 것이, 함수형 프로그래밍의 장점이다.

메서드 참조

  • 단순히 메서드 호출로 구성된 람다식을 메서드 참조로 표현
    -> 람다식 조차도 귀찮아서 더 간단하게 사용하고 싶은 니즈를 반영
// 익명 클래스
IntBinaryOperator operator = new IntBinaryOperator(){
	int applyAsInt(int left, int right){ // 추상 메서드를 구현한 것
    	Math.max(left, right);
    }
}

// 기존 람다식
IntBinaryOperator operator = (left, right) -> Math.max(left, right);
// 메서드 참조 사용
IntBinaryOperator operator = Math :: max;

System.out.println(operator.applyAsInt(4,5));

기존 람다식에서 람다식 함수는 단순히 두 개의 매개 변수를 받아와서 Math.max() 에게 전달하는 역할을 한다. 굳이 귀찮게 매개변수를 적기 싫다면 다음처럼 메서드 참조를 사용하여 간단하게 표현할 수 있다.

즉, 메소드 참조는 해당 메소드를 호출하는 것과 같은 의미이다.

생성자 참조

  • 단순히 객체를 생성하고 리턴하도록 구성된 람다식을 생성자 참조로 표현
// 람다식
(a,b) -> {return new 클래스(a,b);};

// 메소드 참조
클래스::new

0개의 댓글