람다식(Lambda expression)

  • 람다식(Lambda expression) : 메서드를 하나의 ‘식(expression)’으로 표현하는 것
  • 람다식은 함수를 간략하면서도 명확한 식으로 표현할 수 있게 해준다.
  • 메서드를 람다식으로 표현하면 메서드의 이름과 반환값이 없어지므로, 람다식을 ‘익명 함수(anonymous function)’이라고도 한다.

  • 객체지향개념에서는 함수(function)대신 객체의 행위나 동작을 의미하는 메서드(method)라는 용어를 사용한다.
  • 메서드는 함수와 같은 의미이지만, 특정 클래스에 반드시 속해야 한다는 제약이 있기 때문에 기존의 함수와 같은 의미의 다른 용어를 선택해서 사용한 것이다.

  • 괄호안의 문장이 return문일 경우 괄호를 생략할 수 없다.
    (int a, int b) -> { return a > b ? a:b; } // OK
    (int a, int b) ->  return a > b ? a:b;  // 에러
    
  • 하나의 메서드가 선언된 인터페이스를 정의해서 람다식을 다루는 것은 기존의 자바의 규칙들을 어깆 ㅣ않으면서도 자연스럽다
  • 그래서 인터페이스를 통해 람다식을 다루기로 결정되었으며, 람다식을 다루기 위한 인터페이스를 ‘함수형 인터페이스(functional interface)’라고 부르기로 했다.
  • 단, 함수형 인터페이스에는 오직 하나의 추상 메서드만 정의되어 있어야 한다는 제약이 있다.
  • 그래야 람다식과 인터페이스의 메서드가 1:1로 연결될 수 있기 때문이다. 반면에 static메서드와 default메서드의 개수에는 제약이 없다.

  • @FunctionalInterface를 붙이면, 컴파일러가 함수형 인터페이스를 올바르게 정의하였는지 확인해주므로 꼭 붙이도록 하자.

예제

변경 전

public class wrapper_test01 {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("abc", "aaa", "bbb", "aaa");

        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
    }
}

변환 후(람다)

public class wrapper_test01 {

    public static void main(String[] args) {
        List<String> list = Arrays.asList("abc", "aaa", "bbb", "aaa");

        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);
            }
        });
    }
}

forEach 예제

  • forEach를 사용해서 간편하게 List, Map의 값들을 제어할 수 있다.
public class lamdaTest01 {
    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();
        for(int i=0; i < 10; i++) {
            list.add(i);
        }

        System.out.println(list);

        // list의 모든 요소 출력
        list.forEach(i -> System.out.print(i + ","));
        System.out.println(); // 0,1,2,3,4,5,6,7,8,9,

        // list에서 2 or 3의 배수를 제거한다.
        list.removeIf(x -> x%2 == 0 || x%3 == 0);
        System.out.println(list); // [1, 5, 7]


        HashMap<String,String> map = new HashMap<>();
        map.put("1", "11");
        map.put("2", "22");
        map.put("3", "33");
        map.put("4", "44");
        
        // Map 모든 요소를 key,value 형식으로 출력
        map.forEach((k,v) -> System.out.println(k + " :: " + v));
        //1 :: 11
        //2 :: 22
        //3 :: 33
        //4 :: 44
    }
}