전체 코드
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));