본문 바로가기
TIL (Today I Learned)/Java

TIL 230321(화) 람다식, 함수형 인터페이스, 메소드 참조

by 꼬순내 개발 2023. 3. 21.
SMALL

 

 

 

 

 

람다식

 : 함수(메소드)를 하나의 '식(expression)'으로 표현한 것

   함수를 간략하고 명확하게 표현할 수 있게 해줌

   '익명 함수(anonymous function)' 라고도 함 ( 메소드의 이름과 반환값이 없어짐)

   메소드의 매개변수로 전달되어지는 것이 가능

   메소드의 결과로 반환 될 수도 있음

   람다식으로 인해 메소드를 변수처럼 다루는 것이 가능하게 됨

 

 

 

 

람다식 작성

ㅡ> 메소드에서 이름과 반환타입을 제거,  매개변수 선언부와 몸통{ } 사이에 '->' 추가하면됨

 

작성법     람다식
  int max(int a, int b) {
   return a > b ? a : b;
}
ㅡ> (int a, int b) -> {
  return a > b ? a: b;
}
반환값이 있는 메소드
: 식 이나 값만 적고 return문 생략,
끝에 ; 안붙임
(int a, int b) -> { return a > b ? a : b; } ㅡ> (int a, int b) -> a > b ? a : b
람다식에 선언된 매개변수의 타입이 추론 가능한 경우,  생략가능 (int a, int b) -> a>b ? a : b ㅡ> (a,b)-> a > b ? a : b
선언된 매개변수가 하나뿐인 경우,
괄호( )생략 가능
단, 매개변수의 타입이 있으면 괄호( ) 생략 불가
(a) -> a*a
(int a) -> a*a
ㅡ> a      -> a*a  //OK
int a  -> a*a //에러
괄호{ }안에 문장이 하나일 때는
괄호{ }생략 가능
이 때, 문장 끝에 ;붙이지 않음
(String name, int i) -> {
System.out.println(name+"="+i);
}
ㅡ> (String name, int i) ->
System.out.println
(name+"="+i)

 

 

 

 

람다식은 익명클래스의 객체와 동등함

 

 

함수형 인터페이스(Functional Interface)

 : 람다식을 다루기 위한 인터페이스

   단 하나의 추상메소드만 정의되어 있어야함

interface Myfunction {
	public abstract int max(int a, int b);
    }
    
  // 위 인터페이스를 구현한 익명 클래스의 객체 생성
  My function f = new MyFunction() {
  		public int max(int a, int b) {
        return a > b ? a : b;
        }
      };
   int big = f.max(5,3);  // 익명 객체의 메소드를 호출
   
   //익명 객체를 람다식으로 대체 가능
   MyFunction f = (int a, int b) -> a > b ? a : b;  
   int big = f.max(5,3);  // 익명 객체의 메소드를 호출

 

 

 

 

람다식을 참조변수로 다룰 수 있음 ㅡ> 메소드를 통해 람다식을 주고받을 수 있음

( 즉, 변수처럼 메소드를 주고받는 것이 가능)

사실상, 메소드가 아니라 객체를 주고받는 것이라 근본적으로 달라진 것은 없으나 람다식 덕분에 코드가 간결하고 쉬워짐

//함수형 인터페이스 MyFunction정의
@FunctionalInterface    //컴파일러가 체크해줌
interface MyFunction {
	void myMethod();     //추상 메소드
 }
 
 void aMethod(MyFunction f) {  // 매개변수의 타입이 함수형 인터페이스
 	f.myMethod();              // MyFunction에 정의된 메소드 호출
    }
    ...
    Myfunction f = () -> System.out.println("myMethod()");
    aMethod(f);
    
    //참조변수 없이 직접 람다식을 매개변수로 지정 가능
    aMethod(()-> System.out.println("myMethod()"));  //람다식을 매개변수로 지정

 

메소드의 반환타입이 함수형 인터페이스타입이면, 함수형 인터페이스의 추상메소드와 동등한 람다식을 가리키는 참조변수를 반환하거나 람다식을 직접 반환 가능

MyFunction MyMethod() {
	MyFunction f = ()->{};
    	return f;       // 이 줄과 윗 줄을 한 줄로 줄이면, return()->{};
 }

 

 

 

 

 

java.util.function패키지에 일반적으로 자주 쓰이는 형식의 메소드를 함수형 인터페이스로 미리 정의해 놓았음

가능하면 이 패키지의 인터페이스를 활용하는것이 좋음

 

<자주 쓰이는 가장 기본적인 함수형 인터페이스>

<출처> 자바의 정석

 

Ex) java.util.function패키지 예제

 

 

 

 

 

여러 Predicate(조건식)을 and( ), or( ), negate( )로 연결해서 하나의 새로운 Predicate으로 결합 할 수 있음

static메소드인 isEquals( )는 두 대상을 비교하는 Predicate을 만들때 사용

 ( isEqual(  )의 매개변수로 비교대상을 하나 지정하고, 또 다른 비교대상은 test( )의 매개변수로 지정

 

 

 

 

함수형 인터페이스를 사용하는 컬렉션 프레임웍 인터페이스

<출처> 자바의 정석

 

Ex)

 

 

 

 

 

 

메소드 참조

 : 람다식이 하나의 메소드만 호출하는 경우, 메소드 참조를 이용하여 람다식을 간략히 할 수 있음

   ' 클래스이름::메소드이름' 또는 '참조변수::메소드이름'으로 바꿀 수 있음

   생성자를 호출하는 람다식도 메소드 참조로 변환할 수 있음

   메소드 참조는 람다식을 마치 staitc변수처럼 다룰 수 있게 해줌

Supplier<MyClass> s = () -> new MyClass();  // 람다식
Supplier<MyClass> s = MyClass::new;         // 메소드 참조

Function<Integer, MyClass> f = (i) -> newMyClass(i);  // 람다식
Function<Integer, MyClass> f2 = MyClass::new;         // 메소드 참조

BiFunction<Integer, String, MyClass> bf = (i, s) -> new MyClass(i,s);
BiFunction<Integer, String, MyClass> bf2 = MyClass::new;    //메소드 참조

//배열
Function<Integer, int[]> f = x -> new int[x];   // 람다식
FUnction<Integer, int[]> f2 = int[]::new;       // 메소드 참조

 

 

 

 

 

 

 

 

 

 

 

 

 

LIST

댓글