-
자바 8 - 함수형 인터페이스 Predicate<T>Java, Kotlin, Spring 2022. 1. 12. 08:06
자바의 람다 표현식 - 정의와 사용방법에 이어서 자바의 람다 표현식 - 활용 방법 까지 알아보았다.
자바 8 버전에는 람다와 메소드 참조를 쉽게 사용할 수 있도록 도와주는 함수형 인터페이스들을 제공한다.
함수형 인터페이스들은
java.util.function
패키지에 정의되어 있다. 제공하는 인터페이스의 종류는 공식문서에서 확인하자.이 포스팅에서 사용한 예제코드는 Github 에서 확인할 수 있다.
1. 사전 준비
우리는
Predicate<T>
,Consumer<T>
그리고Function<T, R>
를 알아볼 것이다.
각각의 함수형 인터페이스를 사용할 객체로Vehicle
클래스를 만들어서 사용해보자.public class Vehicle { private Type type; private String vendor; private String modelName; private String color; public Vehicle( Type type, String vendor, String modelName, String color ) { this.type = type; this.vendor = vendor; this.modelName = modelName; this.color = color; } public enum Type { SUV, SEDAN, TRUCK } // getters }
타입, 제조사, 모델 이름, 색상을 프로퍼티로 갖는 클래스이다.
2. 조건 검사 - if else
Vehicle
클래스를 인스턴스화 시킨vehicle
이 있다.Vehicle vehicle = new Vehicle(Vehicle.Type.SUV, "BMW", "M3", "white");
vehicle
이SUV
타입인지 검사하고자 할 때, 가장 기본적인 방법은 if else 조건문이다.if (Vehicle.Type.SUV.equals(vehicle.getType())) { // ... } else { // ... }
일반적으로 위와 같은 조건 검사 코드를 위임하고 싶을 때가 있는데, 조건 검사 코드가 매우 많아져서 주요 관심사를 확인하기 어렵거나, 다양한 방식으로 응용이 필요한 순간이다.
조건 검사를 실행하는 역할을 가진 객체를 분리하여 기능을 위임해 보려고 한다.
3.
Predicate<T>
java.util.function.Predicate<T>
인터페이스는test
메소드를 추상 메소드로 선언한 함수형 인터페이스다.실제 코드는 아래와 같은 모습이다.
@FunctionalInterface public interface Predicate<T> { boolean test(T t); // ... }
4.
Predicate<T>
인터페이스를 구현한 구체 클래스 만들기Predicate<T>
를 구현한 구체 클래스부터 만들어보자.Vehicle
객체의 인스턴스가SUV
타입인지 검사하는 구체 클래스이다.public class VehicleSUVPredicate implements Predicate<Vehicle> { @Override public boolean test(Vehicle vehicle) { return Vehicle.Type.SUV.equals(vehicle.getType()); } }
Predicate<T>
인터페이스의 Generic 타입에Vehicle
클래스를 사용하겠다고 명시해 두었다. 따라서 클래스의 이름에도 prefix로Vehicle
을 사용했다.
구현한 코드는SUV
여부를 확인하고 있다.
5. 구체 클래스를 이용하여
Vehicle
타입 검사하기구현한 구체 클래스를 사용할 서비스 클래스를 선언한다.
public class VehiclePredicateService { private final Vehicle vehicle; private final VehicleSUVPredicate vehicleSUVPredicate; public VehiclePredicateService() { vehicle = new Vehicle(Vehicle.Type.SUV, "BMW", "M3", "white"); vehicleSUVPredicate = new VehicleSUVPredicate(); } public void predicate() { boolean isSuv = vehicleSUVPredicate.test(vehicle); } }
Predicate<T>
를 구현한 코드를VehicleSUVPredicate
클래스에 캡슐화하였고, 클라이언트에서는 해당 클래스의 인스턴스에 의존하여 결과를 얻고 있다.
6. 람다 적용
함수형 인터페이스를 인수로 받는 메소드가 준비되면, 람다를 사용할 수 있다.
이번에는
SUV
와 같은 특정 요소에 대한 검사가 아니라,Vehicle
객체에 대한 검사를 할 수 있는 역할을 가진 클래스를 만들어보자.public class VehiclePredicator { private final Vehicle vehicle; public VehiclePredicator(Vehicle vehicle) { this.vehicle = vehicle; } public boolean predicate(Predicate<Vehicle> predicate) { return predicate.test(vehicle); } }
VehiclePredicator
는vehicle
을 프로퍼티로 가지며,Predicate<Vehicle>
을 인수로 받고boolean
을 리턴하는 메소드predicate
를 가지고 있다.
이제 이 클래스가 람다와 함께 사용되어 어떤 역할을 수행할 수 있는지 확인해보자.public class VehiclePredicateService { // ... public void predicate() { boolean isSuv = vehiclePredicator.predicate( (Vehicle vehicle) -> vehicle.getType().equals(Vehicle.Type.SUV) ); boolean isSedan = vehiclePredicator.predicate( (Vehicle vehicle) -> vehicle.getType().equals(Vehicle.Type.SEDAN) ); boolean isSedanAndGreenColor = vehiclePredicator.predicate( (Vehicle vehicle) -> vehicle.getType().equals(Vehicle.Type.SEDAN) && vehicle.getColor() == "green" ); boolean isBMW = vehiclePredicator.predicate( (vehicle) -> vehicle.getVendor() == "BMW" ); } }
VehiclePredicator
는Vehicle
에 관련된 검사를 수행할 수 있고, 검사 로직이 람다 표현식으로 제공될 수 있다.
검사를 수행하는 로직이 클래스의 메소드 내에서만 존재할 수 있었던 이전과 달리, 자바 8 버전부터는 람다를 이용하여 검사 로직을 독립적인 함수의 형태로 구현할 수 있다.따라서 여러 검사 로직을 하나 하나 구체 클래스로 구현하지 않아도, 다양한 형태의 구현이 가능해졌다.
다음 포스팅에서는
Consumer<T>
를 알아도록 하겠다.반응형'Java, Kotlin, Spring' 카테고리의 다른 글
자바 8 - 함수형 인터페이스 Consumer<T> (0) 2022.01.12 자바 Iterable, Iterator, Collection, List 분석하기 (0) 2022.01.12 자바의 람다 표현식 2 - 활용 방법 (0) 2022.01.12 자바의 람다 표현식 1 - 정의와 사용방법 (0) 2022.01.12 Spring Security 간단 용어 정리 (0) 2022.01.12