[내배캠 Java 6기] 함수형 프로그래밍

ekkkyo_j·2024년 8월 2일

[내배캠 Java 6기] TIL

목록 보기
10/38

전체 코드

package week05.thread.modern;

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<>();

        // 주말 주차장
        ArrayList<Car> weekendParkingLot = 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);

//        parkingLot.addAll(parkingCarWithTicket(carsWantToPark)); // 티켓이 있는 차량만 주차할 수 있다.
        parkingLot.addAll(parkCars(carsWantToPark, Car::hasTicket));

//        parkingLot.addAll(parkingCarWithMoney(carsWantToPark)); // 일정량 이상의 돈이 있는 차량만 주차할 수 있다.
        parkingLot.addAll(parkCars(carsWantToPark, Car::noTicketButMoney));

        //  익명 함수 사용
        parkingLot.addAll(parkCars(carsWantToPark, (Car car)-> car.hasParkingTicket() && car.getParkingMoney()>1000));

        for (Car car : parkingLot) {
            System.out.println("Parked Car : " + car.getCompany() + "-" + car.getModel());
        }


    }

    public static List<Car> parkingCarWithTicket(List<Car> carsWantToPark) {
        ArrayList<Car> cars = new ArrayList<>();

        for (Car car : carsWantToPark) {
            if (car.hasParkingTicket()) { // 티켓이 있는가?
                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) { // 티켓은 없지만 돈이 있는 차량 추가해주기
                cars.add(car);
            }
        }

        return cars;
    }

    // 위의 두 메소드를 하나로!!
    // 내부 주요 로직을 함수로 전달받자!
    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);

}

뜯어보기

        // 주차 대상 차량
        ArrayList<Car> carsWantToPark = new ArrayList<>();

        // 주차장
        ArrayList<Car> parkingLot = new ArrayList<>();

        // 주말 주차장
        ArrayList<Car> weekendParkingLot = new ArrayList<>();

순서대로,
주차장에 차를 대고 싶어하는 차량의 List
주차장 List
주말 주차장 List 이다.

Car class 코드

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;
    }
}

변수 field

  • 자동차 회사(company)
  • 자동차 모델(model)
  • 티켓유무(hasParkingTicket)
  • 주차장 요금을 낼 돈(parkingMoney)
public Car(String company, String model, boolean hasParkingTicket, int parkingMoney) {
        this.company = company;
        this.model = model;
        this.hasParkingTicket = hasParkingTicket;
        this.parkingMoney = parkingMoney;
    }

생성자 함수
company, model, hasParkingTicket, parkMoney field를 받아 초기화한다.

        // 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);

5개의 car instance를 선언할 때 위의 field를 설정하여 초기화하였다.

    public String getCompany() {
        return company;
    }

    public String getModel() {
        return model;
    }

    public boolean hasParkingTicket() {
        return hasParkingTicket;
    }

    public int getParkingMoney() {
        return parkingMoney;
    }

company 값 반환
model 값 반환
ticket을 갖고 있으면 true 반환 아니면 false 반환
parkingMoney 반환

    public static List<Car> parkingCarWithTicket(List<Car> carsWantToPark) {
        ArrayList<Car> cars = new ArrayList<>();

        for (Car car : carsWantToPark) {
            if (car.hasParkingTicket()) { // 티켓이 있는가?
                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) { // 티켓은 없지만 돈이 있는 차량 추가해주기
                cars.add(car);
            }
        }

        return cars;
    }

    // 위의 두 메소드를 하나로!!
    // 내부 주요 로직을 함수로 전달받자!
    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;
    }

위의 두 메소드가 형식이 비슷하므로, 아래 parkCars로 refactoring한다.

interface Predicate<T> {
    boolean test(T t);
}

위의 interface를 활용하여, parkCars의 매개변수로 Predicate function을 넣어 인터페이스 Predicate을 사용한다.
그리고, 두 메소드의 내부 로직을 함수로 전달하여 구현한다.

    public static boolean hasTicket(Car car) {
        return car.hasParkingTicket;
    }

    public static boolean noTicketButMoney(Car car) {
        return !car.hasParkingTicket && car.getParkingMoney() > 1000;
    }

Car 클래스 내부에 위의 두 메서드를 생성한다.
hasTicket 메서드는 Car 객체를 입력 받아 해당 객체가 티켓을 가지고 있으면 true 아니면 false를 반환한다.
noTicketButMoney 함수는 Car 객체를 입력 받아, 해당 객체가 티켓이 없고 주차장 요금을 낼 돈이 1000원 이상인 경우 true를 반환 두 조건을 만족하지 않으면 false 반환한다.

//        parkingLot.addAll(parkingCarWithTicket(carsWantToPark)); // 티켓이 있는 차량만 주차할 수 있다.
        parkingLot.addAll(parkCars(carsWantToPark, Car::hasTicket));

//        parkingLot.addAll(parkingCarWithMoney(carsWantToPark)); // 일정량 이상의 돈이 있는 차량만 주차할 수 있다.
        parkingLot.addAll(parkCars(carsWantToPark, Car::noTicketButMoney));

parkCars 함수의 매개변수로, carsWantToPark와 Car class에 선언한 클래스를 넣어 티켓이 있는 차량과 1000원 이상 있는 차량만 주차할 수 있도록 한다.

주말에는 티켓도 있고, 1000원 이상인 차량만 등록할 수 있다. 익명 함수 사용를 사용하여 구현한다.

parkingLot.addAll(parkCars(carsWantToPark, (Car car)-> car.hasParkingTicket() && car.getParkingMoney()>1000));
profile
게으르지만 성실히 공부하기^_^

0개의 댓글