자바 - 람다식

SeungTaek·2021년 8월 21일
0

자바(Java)

목록 보기
1/8
post-thumbnail

본 게시물은 스스로의 공부를 위한 글입니다.
틀린 내용이 있을 수 있습니다.

📒 람다식이란

  • y=f(x)형태의 함수로 구성된 프로그래밍 기법
  • 객체 지향 프로그래밍보다는 대용량 데이터를 처리하거나 이벤트 지향 프로그래밍에 유리하다.
  • 따라서 객체 지향 프로그래밍과 함수적 프로그래밍을 적절히 섞어서 사용하는게 중요하다.

📌 자바8부터 함수적 프로그래밍 지원

  • 람다식을 언어 차원에서 제공해준다.

  • (타입 매개변수, ...) -> {실행문; ...}

  • 장점: 코드가 매우 간결해진다. 컬렉션 요소를 필터링 또는 매핑해서 쉽게 집계할 수 있다.

  • 자바는 람다식을 함수적 인터페이스의 익명 구현 객체로 취급한다.

함수적 인터페이스란 한개의 메소드를 가지고 있는 인터페이스이다.

  • 인터페이스면 어디선가 구현을 해야 할 텐데, 아래와 같이 할 수 있다.
Runnable runnable = new Runnable(){
	public void run(..) {...}
};

Runnable runnable = (..)->{...}; //람다식 변환!
  • 어차피 함수적 인터페이스는 메소드가 한개이기 때문에, 람다식으로 구현한 함수가 어떤 메소드인지 자바가 안다.

📒 람다식 기본 문법

  • 기본 모양
    • (타입 매개변수, ...) -> {실행문; ... }
    • (int a) -> {System.out.println(a);};
  • 매개 타입은 자동으로 인식하기 때문에 생략 가능(이미 인터페이스에서 정의 했으므로)
    • (a)->{System.out.println(a);};
  • 하나의 매개변수만 있을 경우에는 괄호 생략 가능
    • a->{System.out.println(a);};
  • 하나의 실행문만 있다면 중괄호 생략 가능
    • a-> System.out.println(a)
  • 매개변수가 없다면 괄호를 생략할 수 없음
    • ()->{실행문;...};
  • 리턴값이 있는 경우, return 문을 사용
    • (x, y)-> {return x+y;};
  • 중괄호에 return 문만 있을 경우, 중괄호를 생략 가능
    • (x, y) -> x+y

📒 타겟 타입과 함수적 인터페이스

📌 타겟 타입(Target type)

  • 람다식의 대입되는 인터페이스
  • 익명 구현 객체를 만들 때 사용할 인터페이스
  • 인터페이스 변수=람다식;

📌 @FunctionalInterface

  • 하나의 추상 메소드만 가지는지 컴파일러가 체크하도록 한다.

  • 두 개 이상의 추상 메소드가 선언되어 있으면 컴파일 오류 발생

📌 예시

함수적 인터페이스 선언

@FunctionalInterface
public interface MyFunctional{
	public void method();
}

람다식으로 익명 구현 객체 구현

MyFunctional fi=()->{...}

사용하는 법

fi.method();

📒 자바에서 제공되는 함수적 인터페이스

1. Function<T, S>

  • 입력 타입 T를 주면, 타입 S를 리턴해주는 인터페이스
  • apply를 구현하면 된다.
Function<Integer, Integer> plus10=(i)->i+10;
System.out.println(plus10.apply(1));
  • 함수 조합하기
    • compose: F1.compose(F2);
      • F2를 실행 후 나오는 리턴값을 F1의 인자값으로 사용
    • andThen: F1.andThen(F2);
      • F1을 실행 후 나오는 리턴값을 F2의 인자값으로 사용
Function<Integer, Integer> plus10=(i)->i+10;
Function<Integer, Integer> multiply2=(i)->i*2;

Function<Integer, Integer> multiply2AndPlus10=plus10.compose(multiply2));
Function<Integer, Integer> plus10AndMultiply2=plus10.andThen(multiply2));

System.out.println(multiply2AndPlus10(2));

2. BiFunction<T, U, R>

  • 두 개의 값(T, U)를 받아서 R 타입을 리턴하는 함수 인터페이스
  • R apply(T t, U u)

3. Consumer<T>

  • T 타입을 받아서 아무값도 리턴하지 않는 함수 인터페이스
  • void Accept(T t)
  • 함수 조합용 메소드: andThen

4. Supplier<T>

  • T 타입의 값을 제공하는 함수 인터페이스. 인풋이 없고, 아웃풋만 한개 있음.
  • T get()

5. Predicate<T>

  • T 타입을 받아서 boolean을 리턴하는 함수 인터페이스
  • boolean test(T t)
  • 함수 조합용 메소드
    • And
    • Or
    • Negate

6. UnaryOperator<T>

  • Function<T, R>의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수 인터페이스

7. BinaryOperator<T>

  • BiFunction<T, U, R>의 특수한 형태로, 동일한 타입의 입렵값 두개를 받아 리턴하는 함수 인터페이스

자바에서 제공하는 인터페이스 더보기


📒 람다의 변수 캡처(Variable Capture)

📌로컬 변수 캡처

  • final이거나 effective final 인 경우에만 참조할 수 있다.

  • 그렇지 않을 경우 concurrency 문제가 생길 수 있어서 컴파일가 방지한다.

📌 effective final

  • 자바 8부터 지원하는 기능으로 “사실상" final인 변수.

  • final 키워드 사용하지 않은 변수를 익명 클래스 구현체 또는 람다에서 참조할 수 있다.

  • 익명 클래스 구현체와 달리 ‘쉐도윙’하지 않는다.

    • 익명 클래스는 새로 스콥을 만들지만, 람다는 스콥을 공유한다.
public class local{
    void method(int arg){
        int localVar=40;
        
        MyFunctional fi=()->{
            //arg=31; //final이므로 수정 불가
            //localVar=41; //final이므로 수정 불가
            System.out.println(arg, localVar);
        }
    }
}
private void run() {
	int num=10;
    IntConsumer printlnt=(i)->{
        System.out.println(num+i); //여기의 num 위에서 선언헌 num과 같은 변수이다. 
    };
    //num++; //람다에서 이 변수를 사용중 -> effective final -> 변경할 수 없다.
}

Reference

이것이 자바다.
인프런 더 자바(백기선)

profile
I Think So!

0개의 댓글