alt
Home 자바의정석 - 14장 람다식
Post
Cancel

자바의정석 - 14장 람다식

: 메서드를 하나의 식(expression)으로 표현한 것. 그래서 변수처럼 사용이 가능해진다.

  • JEDK1.8에 추가된 문법.
  • 자바에 함수형 패러다임을 갖도록 한 문법.
  • 자바에서는 기본적으로 메서드를 만들려면 클래스를 만들고, 객체도 생성해야하는데, 이 모든 과정을 생략 가능하게 해준다.


함수형 인터페이스

: 람다식을 변수로 받을 수 있는 참조변수

  • @FunctionalInterface를 사용해 함수형 인터페이스임을 알린다.

  • 단 하나의 abstract 메소드만을 가질 수 있다. 그래야 람다식과 인터페이스의 메서드가 1:1로 연결될 수 있기 때문이다. (default, static 제외)

    • Comparator 내부를 확인해보면 디폴트 메소드를 제외하고는 compare 라는 메서드 하나 있다. (equals()Object 클래스로부터 받은 것)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    @FunctionalInterface
    public interface FooInterface {
        int plus(int a, int b);
    }
      
    // --- 아래와같이 사용
      
    FooInterface f = (x, y) -> x + y; // A
    int result = f.plus(5, 3);
      
    // B
    FooInterface f = new FooInterface() {
        @Override
    		public int plus(int a, int b) {
        		return 0;
      	}
    };
    
    • A와 B는 같다. 함수형 인터페이스를 구현하는 public int~~ 부분을 람다식으로 줄여준 버전이 A


람다와 클로저

: 코드를 실행하는 런타임은 자유변수를 “어떤 박스에 넣고 잠가서” 나중에 함수가 실제로 실행할 때, 사용할 수 있도록 만든다.

  • 함수는 변수가 선언된 바깥 부분의 코드가 이미 실행되고 사라진 한참 후에 실행될지도 모른다. 그럼에도 불구하고 해당 변수의 당시의 상태를 기억하는 클로저의 성질 덕분에 람다에서 외부 변수 참조가 가능하다.


java.util.function

  • java.util.function 패키지에 일반적으로 쓰이는 형식의 메서드가 구현되어있으니, 매번 새롭게 정의하지 말고 이 패키지의 인터페이스를 활용할 것이 권장된다.
  • 이 패키지에 존재하는 함수형 Interface들은 컬렉션 프레임워크에서 몇 메서드들의 매개변수로 받고있다.


인터페이스들

  • Function<T, R> : apply() 메서드를 사용하는 가장 일반적인 함수. 매개변수 하나, 리턴값이 있다.
  • Predicate<T> : test() 메서드 사용. boolean을 반환한다는 점이 Function과 다르다. 조건식을 람다식으로 표현하는데 꽤 많이 사용되는 편
  • Consumer<T>, BiConsumer<T, U> : accept() 메서드를 사용. 매개변수가 1 or 2개인 것이 다르다. 이름 그대로 사용하는 것이라서 반환값이 없다.
  • Supplier<T> : get() 이름 그대로 공급자. consumer와 반대로 매개변수가 없고 반환값만 있다.
  • UnaryOperator<T>, BinaryOperator<T> : 매개변수와 반환형이 일치 T -> T. Binary는 매개변수를 두개 받는다.
  • 이외에도 DoubleToIntFunction, ToIntFunction<T> 등 지네릭이 아닌 기본형(래퍼클래스)을 다루는 Function 들도 존재한다.


합성

  • 수학에서 f(g(x)) 하는 것처럼, 함수형 인터페이스를 합성할 수 있다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    Function<String, Integer> f = x -> 5;
    Function<Integer, String> g = x -> x.toString();
    Function<String, String> h = f.andThen(g); // g.compose(f)
      
    Predicate<Integer> p = i -> i > 100;
    Predicate<Integer> q = i -> i < 200;
    Predicate<Integer> r = i -> i % 2 == 0;
      
    Predicate<Integer> all = p.and(q.or(r));
    


메서드 참조 (A::b)

: String::equals 과 같은 더 간결한 문법도 람다식에 해당한다.

  • 클래스이름::메서드이름’ 혹은 ‘참조변수::메서드이름‘의 방식으로 가능하다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    
    () -> new myClass();
    (a, b) -> new myClass(a, b);
      
    x -> new int[x];
      
    // 위의 expression이 아래로 가능
    myClass::new;
      
    int[]::new;
    



Reference)

자바의 정석 3판

자바 개발자를 위한 함수형 프로그래밍

This post is licensed under CC BY 4.0 by the author.

커밋의 상태와 .git

자바의정석 - 14장 스트림