I want to optimalize my code. I used to use for loops and ifs, but I know that there is more faster ways than this. I am still pretty new to the lambdas and streams. For practise, I decided I replace my old codes with them. I am curious, how this code below could change.
int counter = 0;
List<Integer> points = new ArrayList<>();
for (String name : names) {
for (Car car : cars) {
if (counter != 0) {
points.add(counter);
}
counter= 0;
for (Driver driver : car.getDriversWhoDrivesIt()) {
if (driver.getYearsInMotorsport() == 15) {
if (!(names.contains(driver.getName()))) {
filteredCars.remove(car);
counter= 0;
break;
}
}
if (driver.getYearsInMotorsport() == 7 ) {
counter = 7;
}
if (driver.getYearsInMotorsport() == 3) {
counter = 3;
}
}
}
}
So the task here is that there is a list (names) with the drivers which earlier the user define. After that I iterate through all the drivers that drive that cars and if somebody has exactly 15 years of experience and the user not selected it (in the names list), than the car that the driver drived got eliminated (removed from the filteredCar and no need to continue with that car).
So for example I have 3 cars and the drivers with exp:
- car : Lewis(15years), Marco(4), Sebastian(15)
- car: Max(15), Amanda(7)
- car: Bob(15), George(3), Lando(15)
Than the user defines the names: Lewis, Bob, Amanda, Lando, Max
If the driver has 15 years of exp and the user not defined it, than I dont want that car in my filteredCars. And if all the 15 years of exp drivers defined I want to collect the other drivers exp(counter)
So in the end I want my filteredCar list like this: 2. car - 7 3.car - 3
Explanation: The first car got eliminated, because the user not defined Sebastian who has 15 years. The second and third car got promoted, because the user defined all the 15 years experienced drivers, and the second car got 7 point(cuz Amanda), and the third got 3 (George).
I tried to solve this problem with flatMap. But I am got stucked with the if-s. My problem is that I need to use inline if in lambdas but my if-s dont have else part.
names.stream()
.flatMap(name -> cars.stream()
.flatMap(car -> car.getDriversWhoDrivesIt().stream()
// .flatMap(driver -> driver.getYearsInMotorsport() == 5 ? ) //?? now what?
)
);
I hope somebody can help me with this.
CodePudding user response:
I know that there is more faster ways than this
Only faster to write and some may find it more readable.
In this example I'm removing the cars, that have a driver with 15 years experience and aren't listed in the names list, from the stream. Then I just collect the result into a map. Key is the car. Value is the sum of the drivers years - the drivers that have 15 years of experience.
Map<Car, Integer> filteredCars = cars.stream()
.filter(car -> car.driversWhoDrivesIt().stream().allMatch(driver -> driver.yearsInMotorsport() != 15 || names.contains(driver.name())))
.collect(Collectors.toMap(
Function.identity(),
car -> car.driversWhoDrivesIt().stream()
.mapToInt(Driver::yearsInMotorsport)
.filter(y -> y != 15)
.sum()));
CodePudding user response:
Instead of the list of names I would advise defining a Set
. For each Car
filter drivers that have exactly 15
year of experience and then check whether all they are present in the user-difined set of names using allMatch()
operation.
Then collect all the Car
objects remained in the stream into a map using collector toMap()
:
Set<String> names = Set.of("Lewis", "Bob", "Amanda", "Lando", "Max");
List<Car> cars = List.of(
new Car("Car1", List.of(new Driver("Lewis", 15),
new Driver("Marco", 4),
new Driver("Sebastian", 15))
),
new Car("Car2", List.of(new Driver("Max", 15),
new Driver("Amanda", 7))
),
new Car("Car3", List.of(new Driver("Bob", 15),
new Driver("George", 3),
new Driver("Lando", 15))
)
);
Map<Car, Integer> pointByCar = cars.stream()
.filter(car -> car.getDrivers().stream()
.filter(driver -> driver.getYearsInMotorsport() == 15)
.map(Driver::getName)
.allMatch(names::contains)
)
.collect(Collectors.toMap(
Function.identity(),
car -> car.getDrivers().stream()
.mapToInt(Driver::getYearsInMotorsport)
.filter(i -> i == 7 || i == 3)
.sum()
));
pointByCar.forEach((car, points) -> System.out.println(car " -> " points));
Output:
Car{name='Car2'} -> 7
Car{name='Car3'} -> 3