'JDK 1.8의 특징이 뭔가요?' 라고 묻는다면, 단연 람다와 스트림이 아닐까? (여기서 스트림은 흔히 I/O에서 말하는 스트림과는 다른 개념이다.)

 

 

 

람다 ( Lambda )


람다 표현식을 간단히 정의하면 메서드를 하나의 식으로 표현한 것.

int add(int a, int b) {
    return a + b;
}

// 위의 메서드를 람다 표현식으로 나타내면 아래와 같다.
(a, b) -> a + b;

 

Java에서 모든 것은 객체다. 위와 같은 람다 표현식은 사실 익명 클래스의 발전된 형태이다.

익명 클래스에서 파라미터의 갯수와 반환값이 같다면 어떤 메서드인지 추론이 가능하다는걸 이용한 것.

new Object() {
    int add(int a, int b) {
        return a + b;
    }
}

 

람다 표현식이라는게 익명 클래스의 발전된 형태이다보니까, 근본적으로 익명 클래스에 대한 이해가 필요하다.

java.util.Thread 클래스를 예로 들어보자.

public class Main() {

    public static void main(String[] args) {
    
        // Constructor : Thread(Runnable target)

        // 위에서 Runnable은 interface이다.
        // 따라서, 위의 생성자를 호출하려면 Runnable 인터페이스를 구현한 클래스를 파라미터로 전달해야한다.
        // 그런데, Thread를 생성하기 위해 딱 1번 쓰일 뿐인데 클래스 하나를 만들기는 번거롭다.
        // 그래서 아래와 같이 익명 클래스를 사용한다.
        new Thread(new Runnable() {
        
            @Override
            public void run() {
                // do somthing...
                return;
            }
        }).start();


        // 위의 익명 클래스도 가만 보면 너무 장황하다.
        // Runnable 인터페이스를 구현할 익명 클래스가 run() 메서드를 오버라이딩할거라는건 너무 뻔하자나 ?
        // 메서드를 이루는 큰 축은 결국 파라미터와 반환타입 2가지인데, 이걸로 유추할 수 있을거 같은데 ?
        // 파라미터와 반환타입 2가지만 가지고 어떤 메서드를 오버라이딩할지 유추하자.
        // 그래서 나온게 아래와 같은 람다 표현식이다.
        new Thread(() -> {
            // do somthing...
            return;
        }).start();
    }
}

 

위에서 Runnable을 구현하는 익명 클래스를 파라미터로 넘기는 부분을 람다 표현식으로 나타냈는데,

이것이 가능한 이유는 Runnable 인터페이스에서 매개변수가 없고 반환값이 void인 메서드가 하나뿐이기 때문에 추론이 가능하기 때문이다.

당연히, 매개변수가 없고, 반환값도 없는 메서드가 2개 이상이라면 위와 같이 람다로 나타낼 수가 없다. ( 어떤 메서드인지 추론이 불가능하기에 )

 

그럼 익명 클래스에서 람다로 가면서 모든게 좋아졌나? 난 Yes라고 생각한다.

익명 클래스가 가지는 장점을 생각해보자.

  • 익명 클래스는 어떤 인터페이스의 구현체인지 코드에 바로 나타났기 때문에 클래스간의 관계를 파악하기가 수월하다.

 

그런데 가만 생각해보면 람다 표현식을 쓰더라도 참조변수의 타입을 가지고 어떤 인터페이스를 구현하는지도 얼추 유추가 가능하다.

추가적인 장점으로 코드 길이가 줄어들고, 가독성이 높아진다.

 

결론 : 익명 클래스말고 람다 표현식을 사용하자.

 

 

 

스트림 (Stream)


Stream은 Collection류의 객체에 사용할 수 있는 함수형 인터페이스를 통한 간단한 내부 데이터 순회 방법이다.

List<String> strList = Arrays.asList("a", "b", "c", "d");

// 기존에 List와 같은 Collection류의 객체 내부 데이터를 순회하는 방법
for (String str : strList) {
    if (str.equals("c")) {
        return true;
    }
}

// JDK 1.8부터 도입된 Stream을 이용한 데이터 순회 방식
strList.stream()
    .filter(x -> x.equals("c"));

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

[Java] 메서드 참조 ( Method Reference )  (0) 2020.03.24
[Java] .jar와 .war  (0) 2020.03.20
[Java] enum 클래스  (0) 2020.03.04
[Java] default 메서드  (0) 2020.01.29
[Java] Scanner 클래스를 이용한 입/출력  (0) 2019.12.29