简体   繁体   English

用 STREAM 和 LAMBDA 替换 IF 和 FOR 循环

[英]Replace IFs and FOR LOOPs with STREAMs and LAMBDAs

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.我曾经使用 for 循环和 ifs,但我知道还有比这更快的方法。 I am still pretty new to the lambdas and streams.我对 lambda 和流还是很陌生。 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).之后,我遍历所有驾驶这些汽车的司机,如果有人正好有 15 年的经验并且用户没有选择它(在名称列表中),那么司机驾驶的汽车就会被淘汰(从 filteredCar 中删除并且没有需要继续驾驶那辆车)。

So for example I have 3 cars and the drivers with exp:因此,例如我有 3 辆汽车和带有 exp 的司机:

  1. car: Lewis(15years), Marco(4), Sebastian(15)汽车:刘易斯(15 岁)、马可(4 岁)、塞巴斯蒂安(15 岁)
  2. car: Max(15), Amanda(7)汽车:马克斯(15),阿曼达(7)
  3. car: Bob(15), George(3), Lando(15)汽车:鲍勃(15)、乔治(3)、兰多(15)

Than the user defines the names: Lewis, Bob, Amanda, Lando, Max比用户定义的名称: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.如果司机有 15 年的 exp 而用户没有定义它,那么我不希望那辆车出现在我的 filteredCars 中。 And if all the 15 years of exp drivers defined I want to collect the other drivers exp(counter)如果定义了所有 15 年的 exp 驱动程序,我想收集其他驱动程序 exp(counter)

So in the end I want my filteredCar list like this: 2. car - 7 3.car - 3所以最后我想要这样的 filteredCar 列表:2.car - 7 3.car - 3

Explanation: The first car got eliminated, because the user not defined Sebastian who has 15 years.解释:第一辆车被淘汰,因为用户没有定义有 15 年的 Sebastian。 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).第二和第三辆车得到提升,因为用户定义了所有 15 年有经验的司机,第二辆车得到 7 分(因为 Amanda),第三辆车得到 3 分(乔治)。

I tried to solve this problem with flatMap.我试图用 flatMap 解决这个问题。 But I am got stucked with the if-s.但是我被 if-s 困住了。 My problem is that I need to use inline if in lambdas but my if-s dont have else part.我的问题是我需要在 lambda 中使用 inline if 但我的 if-s 没有其他部分。

        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.我希望有人可以帮助我。

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.在此示例中,我要从 stream 中删除具有 15 年经验的驾驶员且未在名称列表中列出的汽车。然后我将结果收集到 map 中。关键是汽车。 Value is the sum of the drivers years - the drivers that have 15 years of experience.价值是司机年数的总和——拥有 15 年经验的司机。

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

Instead of the list of names I would advise defining a Set .我建议定义一个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.对于每个具有恰好15年经验的Car过滤器驱动程序,然后使用allMatch()操作检查它们是否都存在于用户定义的名称集中。

Then collect all the Car objects remained in the stream into a map using collector toMap() :然后使用收集器toMap()将 stream 中剩余的所有Car对象收集到 map 中:

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: Output:

Car{name='Car2'} -> 7
Car{name='Car3'} -> 3

A link to Online Demo在线演示链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM