// 생각해볼 수 있는 함수를 전달하는 방법
public example (매개변수, ... ??? 함수이름) {
// ??? : 함수의 타입
}
interface Predicate<T> {
boolean test(T t);
// 리턴타입 리팩토링할 메서드
}
인터페이스를 선언해서 내부 주요 로직(두 메서드)을 하나의 함수로 전달받도록 만들기
예시) 리팩토링 전
// Ticket이 있는지 확인하는 메서드
public static List<Car> parkingCarWithTicket(List<Car> carsWantToPark) {
ArrayList<Car> cars = new ArrayList<>();
for (Car car : carsWantToPark) {
if (car.hasParkingTicket()) {
// Ticket을 가지고 있을 경우 주차장에 추가
cars.add(car);
}
}
return cars;
}
// 티켓머니가 존재하는지 확인하는 메서드
public static List<Car> parkingCarWithMoney(List<Car> carsWantToPark) {
ArrayList<Car> cars = new ArrayList<>();
for (Car car : carsWantToPark) {
if (!car.hasParkingTicket() && car.getParkingMoney() > 1000) {
// Ticket은 없지만 머니는 1000원을 초과해서가지고 있을 경우 주차장에 추가
cars.add(car);
}
}
return cars;
}
// 변경점 1 : Predicate<Car> 인터페이스를 타입 삼아 함수를 전달
public static List<Car> parkCars(List<Car> carsWantToPark, Predicate<Car> function) {
List<Car> cars = new ArrayList<>();
for (Car car : carsWantToPark) {
// 변경점 2 : 전달된 함수 function을 이용해 검증
if (function.test(car)) {
cars.add(car);
}
}
return cars;
}
import java.util.ArrayList;
import java.util.List;
public class LambdaAndStream {
public static void main(String[] args) {
// 주차 대상 차량
ArrayList<Car> carsWantToPark = new ArrayList<>();
// 주차장
ArrayList<Car> parkingLot = new ArrayList<>();
// 5개의 Car instance
Car car1 = new Car("Benz", "Class E", true, 0);
Car car2 = new Car("BMW", "Series 7", false, 100);
Car car3 = new Car("BMW", "X9", false, 0);
Car car4 = new Car("Audi", "A7", true, 0);
Car car5 = new Car("Hyundai", "Ionic 6", false, 10000);
// 주차대상 차량에 모두 넣음
carsWantToPark.add(car1);
carsWantToPark.add(car2);
carsWantToPark.add(car3);
carsWantToPark.add(car4);
carsWantToPark.add(car5);
// 모든 차량에 대해서 주차장에 주차 시도 : 2가지 검증
// hasTicket : Ticket이 존재해야만 주차 가능
// noTicketButMoney : 주차머니가 존재할 경우 주차 가능
parkingLot.addAll(parkCars(carsWantToPark, Car::hasTicket));
parkingLot.addAll(parkCars(carsWantToPark, Car::noTicketButMoney));
// 주차된 차량 출력
for (Car car : parkingLot) {
System.out.println("Parked Car : " + car.getCompany() + "-" + car.getModel());
}
}
// 익명함수로 리팩토링한 코드 : Predicate<Car> function
public static List<Car> parkCars(List<Car> carsWantToPark, Predicate<Car> function) {
List<Car> cars = new ArrayList<>();
for (Car car : carsWantToPark) {
// 익명함수 사용 코드
if (function.test(car)) {
cars.add(car);
}
}
return cars;
}
}
class Car {
private final String company; // 자동차 회사
private final String model; // 자동차 모델
private final boolean hasParkingTicket;
private final int parkingMoney;
public Car(String company, String model, boolean hasParkingTicket, int parkingMoney) {
this.company = company;
this.model = model;
this.hasParkingTicket = hasParkingTicket;
this.parkingMoney = parkingMoney;
}
public String getCompany() {
return company;
}
public String getModel() {
return model;
}
public boolean hasParkingTicket() {
return hasParkingTicket;
}
public int getParkingMoney() {
return parkingMoney;
}
public static boolean hasTicket(Car car) {
return car.hasParkingTicket;
}
public static boolean noTicketButMoney(Car car) {
return !car.hasParkingTicket && car.getParkingMoney() > 1000;
}
}
interface Predicate<T> {
boolean test(T t);
}
Car::~~~로 사용parkingLot.addAll(parkCars(carsWantToPark, Car::hasTicket));
parkingLot.addAll(parkCars(carsWantToPark, Car::noTicketButMoney));