본문으로 바로가기
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.



람다가 도입된 이유를 크게 기업 환경 변화와 프로그래머들의 요구라고 했는데 이를 좀 더 자세히 살펴보자. 근래에 가장 핫한 용어 가운데 빅데이터가 있다. 기업들은 빅데이터의 분석 및 활용을 통해 기업 전략을 수입하고, 수익을 극대화하고자 한다. 이런 빅데이터 분석은 당연히 ICT 기술을 통해 이뤄질 수밖에 없다. 따라서 프로그래머들에게 빅데이터를 프로그램적으로 다룰 수 있는 방법이 필요해졌다. 그 방법의 중심에는 멀티 코어를 활용한 분산 처리, 즉 병렬화 기술이 필요하다.


지금은 하나의 CPU 안에 다수의 코어를 삽입하는 멀터 코어 프로세서들이 등장하면서 일반 프로그래머에게도 병렬화 프로그램이에 대한 필요성이 생기기 시작했다. 이러한 추세에 대응하기 위해 자바8 에서는 병렬화를 위한 컬렉션(배열, List, Set, Map)을 강화했고, 이러한 컬렉션을 더 효율적으로 사용하기 위해 스트림을 강호했다. 또 스트림을 효율적으로 사용하기 위해 함수형 프로그램이, 다시 함수형 프로그래밍을 위해 람다가, 또 람다를 위해 인터페이스의 변화가수반되었다. 람다를 지원하기 위한 인터페이스를 함수형 인터페이스라고 한다. 이를 정리하면 아래와 같다.


빅데이터 지원 -> 병렬화 강화 -> 컬렉션 강화 -> 스트림 강화 -> 

람다 도입 -> 인터페이스 명세 변경 -> 함수형 인터페이스 도입


물론 람다의 도입이나 함수형 인터페이스 도입이 빅데이터만을 위한 것은 아니지만 주된 이유라고 무방할 것이다


람다란 무엇인가 ?


람다란 한 마디로 코드 블록이다. 기존의 코드 블록은 반드시 메서드 내에 존재해야 했다. 그래서 코드 블록만 갖고 싶어도 기존에는 코드 블록을 위해 메서드를, 다시 메서드를 사용하기 위해 익명 객체를 만들거나 하는 식이였다.하지만 자바 8에서는 이런 수고를 할 필요 없다. 또한 코드 블록인 람다를 메서드의 인자나 반환값으로 사용할 수 있게 됐다. 이것의 의미는 코드 블록을 변수처럼 사용할 수 있다는 것이다.  아래 예제는 기존 방식으로 Runnable 인터페이스 구현체를 사용하는 코드다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A001 implements Runnable{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println("Hello Lambda!!!");
    }
}
 
public class LambdaTest {
    public static void main(String[] args) {
        A001 a1 = new A001();
        a1.run();
    }
}



아래 예제는 위의 코드를 개선해서 클래스 없이 익명 객체를 만들어 사용하는 방법이다. 별도의 클래스 정의 없이 코드 블록인 메서드를 사용하고자 할 때 많이 사용되던 익명 객체를 사용하는 방법이다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
public class LambdaTest {
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println("Hello Lambda2!!!");
            }
        };
        
        r.run();
    }
}



자바 8 이전이라면 이 코드가 최선이라고 할 수 있다. 자바 8은 더 나은 방법을 사용한다. 즉, 익명 객체조차 없이 바로 코드 블록만 사용하면 된다. 아래 예제가 람다를 이용한 예제이다.


1
2
3
4
5
6
7
8
9
public class LambdaTest {
    public static void main(String[] args) {
        Runnable r = () -> {
            System.out.println("Hello Lalbda3!!!");
        };
        
        r.run();
    }
}



위의 3가지 코드를 보면 차이가 있다. 먼저 new Runnable()이 사라질 수 있었는데, Runnable 타입으로 참조 변수 r을 만들고 있으니 new Runnable()은 컴파일러가 알아낼 수 있다.


public void run() 메서드가 단순하게 ()로 변경될 수 있는 이유 역시 간단하다. Runnable 인터페이스가 가진 추상 메서드가 run() 메서드 단 하나이기 때문이다. 마지막으로 추가된 부분은 화살표 기호인 ->다. 이는 람다의 구조가 아래와 같다.


(인자 목록) -> {로직}


람다의 주의해야 할 점


1. 매개변수의 타입을 추론할 수 있는 경우에는 타입을 생략할 수 있다.

2. 매개변수가 하나인 경우에는 괄호(())를 생략할 수 있다.

3. 함수의 몸체가 하나의 명령문만으로 이루어진 경우에는 중괄호({})를 생략할 수 있다. (이때 세미콜론(;)은 붙이지 않음)

4. 함수의 몸체가 하나의 return 문으로만 이루어진 경우에는 중괄호({})를 생략할 수 없다.

5. return 문 대신 표현식을 사용할 수 있으며, 이때 반환값은 표현식의 결과값이다. (이때 세미콜론(;)은 붙이지 않음)


람다에서는 로직이 단 한 줄로 표기되는 경우 블록 기호마저 생략할 수 있다.


1
2
3
4
5
6
7
public class LambdaTest {
    public static void main(String[] args) {
        Runnable r = () -> System.out.println("Hello Lalbda4!!!");
        
        r.run();
    }
}



람다를 이용한 Thread생성 방법


1
2
3
4
5
6
7
8
9
10
11
12
public class LambdaTest {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            System.out.println("Lambda를 이용한 새로운 방법1 !!");
        });
        thread.run();
        
        new Thread(() -> {
            System.out.println("Lambda를 이용한 새로운 방법2 !!");
        }).start();
    }
}



람다 표현식을 사용할 때는 람다 표현식을 저장하기 위한 참조 변수의 타입을 결정해야하는데 이 참조 변수 타입을 함수형 인터페이스라고 한다. 다음 포스트에는 함수형 인터페이스에 대해서 포스팅하겠다.