diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..cfd30dd
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,24 @@
+
+
+ 4.0.0
+
+ org.example
+ SberJavaHomeWork2
+ 1.0-SNAPSHOT
+
+ 17
+ 17
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/ru/sber/mironov/Car.java b/src/main/java/ru/sber/mironov/Car.java
new file mode 100644
index 0000000..1e7e0f0
--- /dev/null
+++ b/src/main/java/ru/sber/mironov/Car.java
@@ -0,0 +1,44 @@
+package ru.sber.mironov;
+
+public class Car {
+ private final long carId;
+ private final String brand;
+ private final String modelName;
+ private final int maxVelocity;
+ private final int power;
+ private final int ownerId;
+
+ public Car(long carId, String brand, String modelName, int maxVelocity, int power, int ownerId) {
+ this.carId = carId;
+ this.brand = brand;
+ this.modelName = modelName;
+ this.maxVelocity = maxVelocity;
+ this.power = power;
+ this.ownerId = ownerId;
+ }
+
+
+ public String getBrand() {
+ return brand;
+ }
+
+ public String getModelName() {
+ return modelName;
+ }
+
+ public int getMaxVelocity() {
+ return maxVelocity;
+ }
+
+ public int getOwnerId() {
+ return ownerId;
+ }
+
+ public long getCarId() {
+ return carId;
+ }
+
+ public int getPower() {
+ return power;
+ }
+}
diff --git a/src/main/java/ru/sber/mironov/Garage.java b/src/main/java/ru/sber/mironov/Garage.java
new file mode 100644
index 0000000..e7ddba5
--- /dev/null
+++ b/src/main/java/ru/sber/mironov/Garage.java
@@ -0,0 +1,128 @@
+package ru.sber.mironov;
+
+import java.util.*;
+
+import static java.util.stream.Collectors.toList;
+
+public interface Garage {
+ HashMap> mapOwnerToCars = new HashMap<>();
+ HashMap mapCarToOwner = new HashMap<>();
+ HashMap> mapBrandToCar = new HashMap<>();
+ HashMap cars = new HashMap<>();
+ HashMap owners = new HashMap<>();
+
+ default Collection allCarsUniqueOwners() {
+ return mapOwnerToCars.keySet().stream()
+ .filter(o -> mapOwnerToCars.get(o).size() == 1)
+ .distinct()
+ .collect(toList());
+ }
+
+ /**
+ * Complexity should be less than O(n)
+ */
+ default Collection topThreeCarsByMaxVelocity() {
+ ArrayList sorted = new ArrayList<>();
+ for (Car car : cars.values()) {
+ sorted.add(car);
+ sorted.sort(Comparator.comparingInt(Car::getMaxVelocity));
+ if (sorted.size() > 3) {
+ sorted.remove(0);
+ }
+ }
+ return sorted;
+ }
+
+ /**
+ * Complexity should be O(1)
+ */
+ default Collection allCarsOfBrand(String brand) {
+ return mapBrandToCar.get(brand);
+ }
+
+ /**
+ * Complexity should be less than O(n)
+ */
+ default Collection carsWithPowerMoreThan(int power) {
+ return mapOwnerToCars.values().stream()
+ .flatMap(Collection::stream)
+ .filter(car -> car.getPower() >= power)
+ .distinct()
+ .collect(toList());
+
+ }
+
+ /**
+ * Complexity should be O(1)
+ */
+ default Collection allCarsOfOwner(Owner owner) {
+ return mapOwnerToCars.get(owner);
+ }
+
+ /**
+ * @return mean value of owner age that has cars with given brand
+ */
+ default int meanOwnersAgeOfCarBrand(String brand) {
+ return (int) mapBrandToCar.get(brand).stream()
+ .map(mapCarToOwner::get)
+ .mapToInt(Owner::getAge)
+ .average().getAsDouble();
+ }
+
+ /**
+ * @return mean value of cars for all owners
+ */
+ default int meanCarNumberForEachOwner() {
+ return (int) mapOwnerToCars.keySet().stream()
+ .mapToInt(owner -> mapOwnerToCars.get(owner).size())
+ .average().getAsDouble();
+ }
+
+ /**
+ * Complexity should be less than O(n)
+ *
+ * @return removed car
+ */
+ default Car removeCar(int carId) {
+ Car deleteCar = cars.get((long) carId);
+ Owner deleteOwner = owners.get((long) deleteCar.getOwnerId());
+
+ mapOwnerToCars.get(deleteOwner).remove(deleteCar);
+ if (mapOwnerToCars.get(deleteOwner).isEmpty()) {
+ mapOwnerToCars.remove(deleteOwner);
+ owners.remove(deleteOwner.getOwnerId());
+ }
+
+ mapBrandToCar.get(deleteCar.getBrand()).remove(deleteCar);
+ if (mapBrandToCar.get(deleteCar.getBrand()).isEmpty()) {
+ mapBrandToCar.remove(deleteCar.getBrand());
+ }
+
+ mapCarToOwner.remove(deleteCar);
+
+
+ cars.remove((long)carId);
+ return deleteCar;
+ }
+
+ /**
+ * Complexity should be less than O(n)
+ */
+ default void addCar(Car car, Owner owner) {
+
+ put(mapOwnerToCars, owner, car);
+ put(mapBrandToCar, car.getBrand(), car);
+
+ mapCarToOwner.put(car, owner);
+ cars.put(car.getCarId(), car);
+ owners.put(owner.getOwnerId(), owner);
+ }
+
+ private void put(HashMap> collectionHashMap, K key, V value) {
+ if (collectionHashMap.containsKey(key)) {
+ collectionHashMap.get(key).add(value);
+ } else {
+ collectionHashMap.put(key, new ArrayList<>(Collections.singletonList(value)));
+ }
+ }
+}
diff --git a/src/main/java/ru/sber/mironov/Main.java b/src/main/java/ru/sber/mironov/Main.java
new file mode 100644
index 0000000..ee9e587
--- /dev/null
+++ b/src/main/java/ru/sber/mironov/Main.java
@@ -0,0 +1,7 @@
+package ru.sber.mironov;
+
+public class Main {
+ public static void main(String[] args) {
+
+ }
+}
diff --git a/src/main/java/ru/sber/mironov/MyGarage.java b/src/main/java/ru/sber/mironov/MyGarage.java
new file mode 100644
index 0000000..17659e7
--- /dev/null
+++ b/src/main/java/ru/sber/mironov/MyGarage.java
@@ -0,0 +1,4 @@
+package ru.sber.mironov;
+
+public class MyGarage implements Garage{
+}
diff --git a/src/main/java/ru/sber/mironov/Owner.java b/src/main/java/ru/sber/mironov/Owner.java
new file mode 100644
index 0000000..021aefc
--- /dev/null
+++ b/src/main/java/ru/sber/mironov/Owner.java
@@ -0,0 +1,31 @@
+package ru.sber.mironov;
+
+public class Owner {
+ private final long ownerId;
+ private final String name;
+ private final String lastName;
+ private final int age;
+
+ public Owner(long ownerId, String name, String lastName, int age) {
+ this.ownerId = ownerId;
+ this.name = name;
+ this.lastName = lastName;
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public long getOwnerId() {
+ return ownerId;
+ }
+
+ public int getAge() {
+ return age;
+ }
+}
diff --git a/src/test/java/ru/sber/mironov/GarageTest/GarageTest.java b/src/test/java/ru/sber/mironov/GarageTest/GarageTest.java
new file mode 100644
index 0000000..c622271
--- /dev/null
+++ b/src/test/java/ru/sber/mironov/GarageTest/GarageTest.java
@@ -0,0 +1,191 @@
+package ru.sber.mironov.GarageTest;
+
+import org.junit.Test;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Assert;
+import ru.sber.mironov.Car;
+import ru.sber.mironov.Garage;
+import ru.sber.mironov.Owner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+
+class Pair {
+ final Owner owner;
+ final Car car;
+
+ Pair(Owner owner, Car car) {
+ this.owner = owner;
+ this.car = car;
+ }
+}
+
+public class GarageTest implements Garage {
+ private ArrayList owners;
+ private ArrayList cars;
+
+ private ArrayList pairs;
+
+
+ @Before
+ public void setUpOwnersAndCars() {
+ Owner o0 = new Owner(6789, "Anton", "qu", 102);
+ Owner o1 = new Owner(1234, "Lexa", "Pak", 37);
+ Owner o2 = new Owner(4321, "Petya", "Lisicin", 42);
+ Owner o3 = new Owner(1894, "Vadim", "Kamushkin", 24);
+ Owner o4 = new Owner(1290, "Olga", "Miroshina", 37);
+ Owner o5 = new Owner(4560, "Svetlana", "Gorkova", 40);
+ Owner o6 = new Owner(4567, "Polina", "kravec", 18);
+
+ Car c0 = new Car(111, "Renault", "duster", 170, 80, 6789);
+ Car c1 = new Car(222, "Lada", "kalina", 40, 30, 6789);
+ Car c2 = new Car(333, "shevrolet", "niva", 10, 5, 6789);
+
+ Car c3 = new Car(123, "Lada", "priora", 100, 20, 1234);
+ Car c4 = new Car(456, "Nissan", "suny", 221, 30, 1234);
+
+ Car c5 = new Car(789, "skoda", "rapid", 220, 10, 4321);
+ Car c6 = new Car(901, "mazda", "bongo", 100, 71, 4321);
+
+ Car c7 = new Car(112, "Opel", "astra", 190, 50, 1894);
+
+ Car c8 = new Car(124, "ford", "focus", 170, 50, 1290);
+
+ Car c9 = new Car(378, "audi", "s5", 250, 100, 4560);
+
+ Car c10 = new Car(192, "Nissan", "Tiida", 180, 60, 4567);
+
+ pairs = new ArrayList<>();
+ pairs.add(new Pair(o0, c0));
+ pairs.add(new Pair(o0, c1));
+ pairs.add(new Pair(o0, c2));
+ pairs.add(new Pair(o1, c3));
+ pairs.add(new Pair(o1, c4));
+ pairs.add(new Pair(o2, c5));
+ pairs.add(new Pair(o2, c6));
+ pairs.add(new Pair(o3, c7));
+ pairs.add(new Pair(o4, c8));
+ pairs.add(new Pair(o5, c9));
+ pairs.add(new Pair(o6, c10));
+
+ owners = new ArrayList<>(Arrays.asList(o0, o1, o2, o3, o4, o5, o6));
+ cars = new ArrayList<>(Arrays.asList(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10));
+
+
+ }
+
+ @Test
+ public void addCarTest() {
+ this.addCar(cars.get(0), owners.get(0));
+ this.addCar(cars.get(1), owners.get(0));
+ this.addCar(cars.get(2), owners.get(0));
+ Assert.assertEquals(this.removeCar((int) cars.get(0).getCarId()), cars.get(0));
+ Assert.assertEquals(this.removeCar((int) cars.get(1).getCarId()), cars.get(1));
+ Assert.assertEquals(this.removeCar((int) cars.get(2).getCarId()), cars.get(2));
+ }
+
+
+ @After
+ public void tearDown() {
+ owners.clear();
+ cars.clear();
+ pairs.clear();
+ }
+
+ @Test
+ public void testTestAllCarsUniqueOwners() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(allCarsUniqueOwners().stream()
+ .sorted(Comparator.comparingLong(Owner::getOwnerId))
+ .collect(toList()),
+ Stream.of(owners.get(3), owners.get(4), owners.get(5), owners.get(6))
+ .sorted(Comparator.comparingLong(Owner::getOwnerId))
+ .collect(toList()));
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestTopThreeCarsByMaxVelocity() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(topThreeCarsByMaxVelocity(), List.of(cars.get(5), cars.get(4), cars.get(9)));
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestAllCarsOfBrand() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(allCarsOfBrand("Lada").stream()
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()), Stream.of(cars.get(1), cars.get(3))
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()));
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestCarsWithPowerMoreThan() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(carsWithPowerMoreThan(40).stream()
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()), Stream.of(cars.get(0), cars.get(6), cars.get(7),
+ cars.get(8), cars.get(9), cars.get(10))
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()));
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestAllCarsOfOwner() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(allCarsOfOwner(owners.get(0)).stream()
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()), Stream.of(cars.get(0), cars.get(1), cars.get(2))
+ .sorted(Comparator.comparingLong(Car::getCarId)).collect(toList()));
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestMeanOwnersAgeOfCarBrand() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(meanOwnersAgeOfCarBrand("Nissan"), 27);
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+ @Test
+ public void testTestMeanCarNumberForEachOwner() {
+ for (Pair p : pairs) {
+ addCar(p.car, p.owner);
+ }
+ Assert.assertEquals(meanCarNumberForEachOwner(), 1);
+ for (Pair p : pairs) {
+ Assert.assertEquals(removeCar((int) p.car.getCarId()), p.car);
+ }
+ }
+
+
+}