본문 바로가기

Java

JAVA8) 람다 표현식

람다 표현식의 특징

  • -> 를 이용한다.
  • 익명 메서드처럼 이름이 없다.
  • 메서드가 아닌 '함수'이다.
  • 간단하다.
  • (매개변수) -> (표현식) 의 형태를 가진다.
  • (매개변수) -> {  표현식; 표현식; .. } 도 가능하다.

 

 

 

1. 일반 익명 메소드를 람다 표현식으로 바꾸기

아래의 함수형 인터페이스가 있다.

public interface Movable {
    int move(int num);
}

 

아래는 Car클래스에 구현하는 버젼이다.

class Car implements Movable {

	@Override
    public int move(int num) {
    	Return num = num * 2;
    }
}

 

재 사용성이 없다면 우리는 익명 메소드를 이용하여 사용할 수 있다.

public static void main(String[] args) {

    Movable movalbe = new Movable() {
    	@Override
        public int move(int num) {
        	return num + num;
        }
    }
}

 

위에서 우리는 람다는 익명 메서드처럼 이름이 없다고 했다.

 

익명 메소드를 람다 표현식을 바꿀 때 어떤점을 고려해서 바꾸는지 알아보면,

  • 변수를 선언할 때 Movable형으로 선언했기에 new Movable() 부분은 컴파일러가 추론 가능
  • 함수형 인터페이스에는 함수가 하나밖에 없으므로 어떤 메소드를 오버라이딩하는지 추론 가능
  • 어떤 메서드를 쓰는지 추론했다면 어떤 인자를 쓰는지도 추론 가능하다. 함수를 사용할 때 인자를 써야하니 생략할 순 없지만 인자의 변수형은 추론할 수 있다.

이 세가지를 바꿔서 람다식으로 바꿔보면,

public static void main(String[] args) {

    Movable movalbe = (num) -> {
    	return num + num;
    };
}

 

여기서 인자가 한개라면 괄호도 생략이 가능하다.

실행 구문이 1줄이면 중괄호도 생략이 가능하다.

실행 구문이 1줄이면 그 실행값의 결과가 리턴값이 된다.

 

최종적으로 아래의 코드를 만들 수 있다.

public static void main(String[] args) {

    Movable movalbe = num -> num + num;
    
    int result = movable(3);
    System.out.print(result); // 6 출력
}

 

5줄이 넘던 것을 한줄로 해결 할 수 있게 되었다.

 

 

 

 

 

람다식은 함수형 인터페이스를 이용하여 추론한다.

함수형 인터페이스는 메소드가 아닌 함수를 이용한다. (입력에 출력이 일정하다)

따라서 람다에서는 인스턴스 필드를 선언할 수 없다. (상태를 가질 수 없다.)

 

 

 

 

람다식의 기본 형태는 아래들이 있다.

  • 기본 :                                       (int num) -> {System.out.println(num);} 
  • 단일 실행문은 중괄호 제거 :       (int num) -> System.out.println(num);
  • 단일 인자는 타입 생략 :              (num) -> System.out.println(num);
  • 단일 인자는 소괄호 제거:            num -> System.out.println(num);
  • 인자가 없으면 소괄호 필수 :        () -> System.out.println("매개변수 없음"); 
  • 인자가 여러개면 소괄호 필수 :     (x, y) -> System.out.println(x, y);
  • 인자가 없고 반환값이 있으면 :      () -> {return value;};
  • 실행코드가 return문 뿐이면 return 키워드 생략 가능 :              () -> value;
  • 매개변수, 리턴타입 둘다 있으면 :   (x, y) -> x+y;

 

 

 

 

람다식은 인자(파라미터)(매개변수)로 입력될 수 있다.

이를 행위 파라미터화 라고 하는데, 메소드의 정의에서 매개변수가 함수형 인터페이스라면,

메소드를 사용할 때 람다식을 매개변수로 전달할 수 있다.

 

 

아래의 Car 클래스가 있다고 치자.

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class Car {
    private String name;

    public Car(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    static List<Car> selectCarList(List<Car> cars, Predicate<Car> predicate){
        List<Car> resultList = new ArrayList<>();
        for(Car car : cars){
            if(predicate.test(car)){
                resultList.add(car);
            }
        }

        return resultList;
    }

}

Predicate는 자바에서 제공하는 함수형 인터페이스로 test()를 추상 메소드로 제공하며 boolean값을 리턴한다.

docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html

 

 

 

selectCarList 메소드를 사용할 떄, 아래와 같이 람다식을 매개변수로 이용할 수 있다.

행위를 전달하므로 행위 파라미터화 라 한다.

    public static void main(String[] args) {

        List<Car> cars = Arrays.asList(new Car("tico"), new Car("sonata"));

        List<Car> result = Car.selectCarList(cars, car -> "tico".equals(car.getName()));

        for (Car car : result) {
            System.out.println(car.getName());
        }
    }

 

 

 

 

참고 :multifrontgarden.tistory.com/124?category=471239

 

Java8#01. 람다 표현식(Lambda Expression)

Java8에서 뭐가 추가됐나요? 라고 물으면 가장 먼저 들리는 대답은 십중팔구 '람다와 스트림이요' 일것이다. 당연히 맞는 말이고 틀린 답은 아니지만 람다와 스트림이 왜 추가됐는지를 알아야하

multifrontgarden.tistory.com

 

'Java' 카테고리의 다른 글

JAVA8) 스트림 API  (0) 2020.12.11
JAVA8) 메소드 레퍼런스  (0) 2020.12.11
JAVA8) 함수형 인터페이스  (0) 2020.12.11
함수형 인터페이스  (0) 2020.12.11
static 메소드 사용  (0) 2020.12.09