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