본문 바로가기
Programming/JAVA

Lambda Expression

by 한 땀; 한 땀; 2020. 12. 10.

 

Lambda Expression(람다식)

  • 익명클래스에서 이름을 지정하지 않고 기본 클래스를 구현했다. 하지만 메소드가 하나뿐인 클래스의 경우 익명클래스도 코드가 간결하지 않고 복잡해보인다. 그래서 나온게 람다식이다.
  • 람다식은 하나의 메소드만 있는 클래스의 인스턴스를 익명클래스 보다 더 간결하게 표현할 수 있다.

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

  • 오직 하나의 추상메소드만 올 수 있으며 default, static 메소드는 정의에 영향이 가지 않으며 하나 이상 올 수 있다.
  • 람다식은 Functional Interfaces(함수형 인터페이스)를 기반으로만 사용할 수 있다.
  • 함수형 인터페이스는 @FunctionalInterface 어노테이션을 사용할 수 있으며 사용을 권장한다.

@FunctionalInterface 어노테이션은 인터페이스의 목적을 명확하게 전달할 뿐만 아니라 함수형 인터페이스의 조건을  충족하지 않는 경우 컴파일러가 에러를 발생시킨다.

 

즉, 아래와 같이 사용할 수 있다.

@FunctionalInterface
interface FunctionalInterfaces<T> {
    T test(T t);
    void test2(); // 이 코드가 삽입되면 @FunctionalInterface 에 의해 컴파일 에러 발생
}

 

다음은 정렬 인터페이스를 구현하는 람다식을 사용하지 않은 코드이다.

@FunctionalInterface
interface Sort<T> {
    boolean sort(T t1, T t2);

    default void swap(List<T> list, int a, int b) {
        T x = list.get(a);
        list.set(a, list.get(b));
        list.set(b, x);
    }
}

class FunctionalSort implements Sort<Integer> {
    @Override
    public boolean sort(Integer t1, Integer t2) {
        return t1 > t2;
    }
}

class TestMain {
    public static void sortFunc(List<Integer> list, Sort<Integer> sort) {
        for (int i = 0; i < list.size() - 1; i++)
            for (int j = i; j >= 0 && sort.sort(list.get(j), list.get(j + 1)); j--)
                sort.swap(list, j, j + 1);

        System.out.print(list);
    }

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 10, 4, 11, 2, 7, 15, 8);
        sortFunc(list, new FunctionalSort());
    }
}

 

sort 함수를 사용하기 위해 Sort 인터페이스를 구현하는 클래스를 만들어 인스턴스를 생성해 전달하는 것을 볼 수 있다.

이는 하나의 기능을 사용하기 위해서 작성되는 불필요한 상용구 코드가 많다는 것을 느낄 수 있다.

 

다음은 람다식을 사용하는 코드이다.

@FunctionalInterface
interface Sort<T> {
    boolean sort(T t1, T t2);

    default void swap(List<T> list, int a, int b) {
        T x = list.get(a);
        list.set(a, list.get(b));
        list.set(b, x);
    }
}

class TestMain {
    public static void sortFunc(List<Integer> list, Sort<Integer> sort) {
        for (int i = 0; i < list.size() - 1; i++)
            for (int j = i; j >= 0 && sort.sort(list.get(j), list.get(j + 1)); j--)
                sort.swap(list, j, j + 1);
                
        System.out.print(list);
    }

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 10, 4, 11, 2, 7, 15, 8);
        sortFunc(list, (a, b) -> a > b); // 람다식 사용
    }
}

 

FunctioanlSort 클래스를 없애고 (a, b) -> a > b 한 문장으로 클래스를 대신하는 것을 볼 수 있다. 

 

 

 

익명 클래스로부터 람다식까지 변환 과정

 

  1. 컴파일러는 sortFunc의 두 번째 매개변수가 Sort <Integer> sort 참조형이므로 인자로 이를 구현하는 인스턴스의 생성문이 올 수 있다는 것을 유추할 수 있다. 따라서 new Sort<Integer>()는 생략이 가능하다.
  2. Sort<Integer> 인터페이스의 추상메소드는 boolean sort(Integer t1, Interger t2) 이므로 이 메소드를 구현한다고 유추할 수 있다. 따라서 public boolean sort는 생략이 가능하다.
  3. 추상메소드 sort의 매개변수형 또한 유추가 가능하므로 Interger를 생략할 수 있다.
  4. return문을 생략하면 알아서 반환의 대상으로 인식한다.

'Programming > JAVA' 카테고리의 다른 글

Effectively final  (0) 2020.12.11
Nested Class, Inner Class  (0) 2020.12.08
Set<E>  (0) 2020.12.02

댓글