diff --git a/src/com/walking/lesson47_method_reference/task1/Main.java b/src/com/walking/lesson47_method_reference/task1/Main.java index a10ca0d68..5ed8fde26 100644 --- a/src/com/walking/lesson47_method_reference/task1/Main.java +++ b/src/com/walking/lesson47_method_reference/task1/Main.java @@ -1,5 +1,7 @@ package com.walking.lesson47_method_reference.task1; +import java.util.List; + /** * Создайте произвольный список элементов. * Выведите каждый из элементов в консоль. @@ -7,5 +9,8 @@ */ public class Main { public static void main(String[] args) { + List strings = List.of("1", "2", "3", "4", "5"); + + strings.forEach(System.out::println); } } diff --git a/src/com/walking/lesson47_method_reference/task2/Main.java b/src/com/walking/lesson47_method_reference/task2/Main.java index d59af5450..a08a50ffa 100644 --- a/src/com/walking/lesson47_method_reference/task2/Main.java +++ b/src/com/walking/lesson47_method_reference/task2/Main.java @@ -1,10 +1,20 @@ package com.walking.lesson47_method_reference.task2; +import java.util.List; + /** * Реализуйте Задачу 1, обернув метод выведения записи в консоль * (System.out.println()) в собственный статический метод. */ public class Main { public static void main(String[] args) { + List integers = List.of(1, 2, 3, 4, 5); + + integers.forEach(Main::print); + } + + private static void print(E element) { + String s = "<" + element + ">"; + System.out.println(s); } } diff --git a/src/com/walking/lesson47_method_reference/task3/Main.java b/src/com/walking/lesson47_method_reference/task3/Main.java index b61a3e9d8..9e0b00422 100644 --- a/src/com/walking/lesson47_method_reference/task3/Main.java +++ b/src/com/walking/lesson47_method_reference/task3/Main.java @@ -1,5 +1,18 @@ package com.walking.lesson47_method_reference.task3; +import com.walking.lesson47_method_reference.task3.exception.UnableParsingException; +import com.walking.lesson47_method_reference.task3.model.CarFilter; +import com.walking.lesson47_method_reference.task3.service.CarService; +import com.walking.lesson47_method_reference.task3.service.CarFilterService; +import com.walking.lesson47_method_reference.task3.model.Car; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + /** * Реализуйте Задачу 3 из урока 46, * описав все реализуемые фильтры через method reference’ы. @@ -7,6 +20,127 @@ * если это не было сделано ранее. */ public class Main { + private static final String COMMAND_OVERVIEW = """ + Для выхода введите exit. + Для поиска введите search <название_фильтра> <значение_фильтра>. + ----------------------- + Поддерживаемые фильтры: + - color <цвет машины> (пример запроса: search color yellow); + - number <номер машины> (пример запроса: search number RR-111-RR); + - partOfNumber <часть номера машины> (пример запроса: search partOfNumber 111); + - yearRange <диапазон годов выпуска> (пример запроса: search yearRange 2015-2016); + ----------------------- + Допускается использование нескольких фильтров в одном запросе в форме: + search <название_фильтра1> <значение_фильтра1> ... <название_фильтраN> <значение_фильтраN>; + Например: + search color yellow partOfNumber 111 yearRange 2015-2016 + ----------------------- + Введите запрос: + """; + public static void main(String[] args) { + CarService carService = new CarService(initCars()); + + try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) { + boolean isTerminateAfterExecute = false; + + while (!isTerminateAfterExecute) { + System.out.println(COMMAND_OVERVIEW); + String input = bufferedReader.readLine(); + String[] arguments = input.split("\\s"); + + isTerminateAfterExecute = executeCommand(arguments, carService); + } + + } catch (IOException e) { + throw new RuntimeException("io exception", e); + } + } + + private static boolean executeCommand(String[] arguments, CarService carService) { + String commandName = arguments[0]; + + return switch (commandName) { + case "exit" -> true; + + case "search" -> { + if (!isValidArguments(arguments)) { + System.out.println("Введено неверное кол-во аргументов"); + } else { + String[] filters = Arrays.copyOfRange(arguments, 1, arguments.length); + List carFilters = parseFilters(filters); + CarFilterService carFilterService = new CarFilterService(carFilters); + List foundCars = carService.findBy(carFilterService::isSuitAll); + printSearchResult(foundCars); + } + + yield false; + } + + default -> { + System.out.println("Неизвестная команда. Работа будет завершена."); + + yield true; + } + }; + } + + private static List initCars() { + Car car1 = new Car("RR-111-RR", 2015, "yellow", true); + Car car2 = new Car("RR-222-RR", 2016, "red", true); + Car car3 = new Car("RR-333-RR", 2017, "yellow", true); + Car car4 = new Car("RR-444-RR", 2018, "red", true); + Car car5 = new Car("RR-555-RR", 2018, "yellow", true); + Car car6 = new Car("RR-666-RR", 2018, "red", true); + Car car7 = new Car("RR-777-RR", 2018, "yellow", true); + Car car8 = new Car("RR-888-RR", 2018, "red", true); + Car car9 = new Car("RR-999-RR", 2018, "yellow", true); + Car car10 = new Car("RR-000-RR", 2018, "red", true); + + return List.of(car1, car2, car3, car4, car5, car6, car7, car8, car9, car10); + } + + private static boolean isValidArguments(String[] arguments) { + return arguments.length >= 3 && arguments.length % 2 != 0; + } + + private static List parseFilters(String[] namesAndValues) { + List carFilters = new ArrayList<>(namesAndValues.length / 2); + + for (int i = 0; i < namesAndValues.length; i++) { + String filterName = namesAndValues[i]; + String filterValue = namesAndValues[++i]; + + if (filterName.equals("yearRange")) { + validateYearRange(filterValue); + } + + carFilters.add(new CarFilter(filterName, filterValue)); + } + + return carFilters; + } + + private static void validateYearRange(String yearRange) { + String yearRangeRegex = "^\\d{4}-\\d{4}$"; + + if (!yearRange.matches(yearRangeRegex)) { + throw new UnableParsingException("Unable parsing year range:", yearRange); + } + } + + private static void printSearchResult(List results) { + System.out.println("-".repeat(23)); + System.out.println("Результаты поиска:"); + + if (results.size() == 0) { + System.out.println("По данному запросу ничего не обнаружено."); + } + + for (Object result : results) { + System.out.println(result); + } + + System.out.println("-".repeat(23)); } } diff --git a/src/com/walking/lesson47_method_reference/task3/exception/UnableParsingException.java b/src/com/walking/lesson47_method_reference/task3/exception/UnableParsingException.java new file mode 100644 index 000000000..b51979c65 --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/exception/UnableParsingException.java @@ -0,0 +1,7 @@ +package com.walking.lesson47_method_reference.task3.exception; + +public class UnableParsingException extends RuntimeException{ + public UnableParsingException(String message, String value) { + super("%s %s".formatted(message, value)); + } +} diff --git a/src/com/walking/lesson47_method_reference/task3/model/Car.java b/src/com/walking/lesson47_method_reference/task3/model/Car.java new file mode 100644 index 000000000..adfa7104d --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/model/Car.java @@ -0,0 +1,50 @@ +package com.walking.lesson47_method_reference.task3.model; + +public class Car { + private final CarIdentifier identifier; + + private String color; + private boolean actualTechnicalInspection; + + public Car(String number, int year, String color, boolean actualTechnicalInspection) { + this(new CarIdentifier(number, year), color, actualTechnicalInspection); + } + + public Car(CarIdentifier identifier, String color, boolean actualTechnicalInspection) { + this.identifier = identifier; + this.color = color; + this.actualTechnicalInspection = actualTechnicalInspection; + } + + public CarIdentifier getIdentifier() { + return identifier; + } + + public String getColor() { + return color; + } + + public void setColor(String color) { + this.color = color; + } + + public boolean isActualTechnicalInspection() { + return actualTechnicalInspection; + } + + public void setActualTechnicalInspection(boolean actualTechnicalInspection) { + this.actualTechnicalInspection = actualTechnicalInspection; + } + + @Override + public String toString() { + return """ + number: %s + year: %d + color: %s + actualTechnicalInspection: %s + """.formatted( + identifier.getNumber(), identifier.getYear(), color, + actualTechnicalInspection ? "actual" : "not actual"); + } +} diff --git a/src/com/walking/lesson47_method_reference/task3/model/CarFilter.java b/src/com/walking/lesson47_method_reference/task3/model/CarFilter.java new file mode 100644 index 000000000..1cc37ae35 --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/model/CarFilter.java @@ -0,0 +1,19 @@ +package com.walking.lesson47_method_reference.task3.model; + +public class CarFilter { + private final String name; + private final String value; + + public CarFilter(String name, String value) { + this.name = name; + this.value = value; + } + + public String getName() { + return name; + } + + public String getValue() { + return value; + } +} diff --git a/src/com/walking/lesson47_method_reference/task3/model/CarIdentifier.java b/src/com/walking/lesson47_method_reference/task3/model/CarIdentifier.java new file mode 100644 index 000000000..45c6908ab --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/model/CarIdentifier.java @@ -0,0 +1,44 @@ +package com.walking.lesson47_method_reference.task3.model; + +import java.util.Objects; + +public class CarIdentifier { + private final String number; + private final int year; + + public CarIdentifier(String number, int year) { + this.number = number; + this.year = year; + } + + public String getNumber() { + return number; + } + + public int getYear() { + return year; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + + if (o == null || !getClass().equals(o.getClass())) { + return false; + } + + CarIdentifier identifier = (CarIdentifier) o; + + return year == identifier.year && Objects.equals(number, identifier.number); + } + + @Override + public int hashCode() { + int hashcode = number.hashCode(); + hashcode += 31 * year; + + return hashcode; + } +} diff --git a/src/com/walking/lesson47_method_reference/task3/service/CarFilterService.java b/src/com/walking/lesson47_method_reference/task3/service/CarFilterService.java new file mode 100644 index 000000000..2fe7edaa1 --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/service/CarFilterService.java @@ -0,0 +1,74 @@ +package com.walking.lesson47_method_reference.task3.service; + +import com.walking.lesson47_method_reference.task3.model.CarFilter; +import com.walking.lesson47_method_reference.task3.model.Car; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +public class CarFilterService { + private final Map filters = new HashMap<>(); + + public CarFilterService(List carFilters) { + for (CarFilter carFilter : carFilters) { + filters.put(carFilter.getName(), carFilter.getValue()); + } + } + + public boolean isSuitAll(Car car) { + Predicate predicate = null; + Predicate current; + + for (String name : filters.keySet()) { + current = choosePredicateBy(name); + + predicate = predicate == null ? current : predicate.and(current); + } + + return predicate != null && predicate.test(car); + } + + public boolean isEqualsColor(Car car) { + return car.getColor() + .equalsIgnoreCase(filters.get("color")); + } + + public boolean isEqualsNumber(Car car) { + return car.getIdentifier() + .getNumber() + .equals(filters.get("number")); + } + + public boolean isContainsPartNumber(Car car) { + return car.getIdentifier() + .getNumber() + .contains(filters.get("partOfNumber")); + } + + public boolean isYearInRange(Car car) { + String yearRange = filters.get("yearRange"); + String[] startAndEnd = yearRange.split("-"); + int startInclusive = Integer.parseInt(startAndEnd[0]); + int endInclusive = Integer.parseInt(startAndEnd[1]); + + return car.getIdentifier() + .getYear() >= startInclusive && car.getIdentifier() + .getYear() <= endInclusive; + } + + private Predicate choosePredicateBy(String name) { + return switch (name) { + case "color" -> this::isEqualsColor; + + case "number" -> this::isEqualsNumber; + + case "partOfNumber" -> this::isContainsPartNumber; + + case "yearRange" -> this::isYearInRange; + + default -> throw new RuntimeException("Unknown filterName" + name); + }; + } +} diff --git a/src/com/walking/lesson47_method_reference/task3/service/CarService.java b/src/com/walking/lesson47_method_reference/task3/service/CarService.java new file mode 100644 index 000000000..acf96f04a --- /dev/null +++ b/src/com/walking/lesson47_method_reference/task3/service/CarService.java @@ -0,0 +1,28 @@ +package com.walking.lesson47_method_reference.task3.service; + +import com.walking.lesson47_method_reference.task3.model.Car; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.function.Predicate; + +public class CarService { + private final List cars = new ArrayList<>(); + + public CarService(Collection cars) { + this.cars.addAll(cars); + } + + public List findBy(Predicate predicate) { + List found = new ArrayList<>(); + + cars.forEach(car -> { + if (predicate.test(car)) { + found.add(car); + } + }); + + return found; + } +}