将带有内部迭代器的增强型 for 循环转换为流

问题描述 投票:0回答:2

我正在尝试将他的一段工作代码转换为流:

Map<Month,Integer> data = new HashMap<>();
for (Scooter scooter : scooters) {
    scooter.getRentalDays().iterator().forEachRemaining(e -> {

        int newVal = scooter.getMileage() * scooter.getMileageRate();
        int curVal = data.getOrDefault(e.getMonth(), 0);
        data.put(e.getMonth(), curVal + newVal);
    });
}

迭代器增加的复杂性给我带来了一个问题,我不知道如何对哈希图中的值求和。下面的示例与上面的代码有些接近,但不支持值的求和。

Map<Month,Integer> data = projects.stream()
        .flatMap(scooter -> scooter.getRentalDays().stream()
                .map(date -> Map.entry(date.getMonth(), scooter.getMileage() * scooter.getMileageRate())))
        .collect(Collectors.toMap(
                Map.Entry::getKey, 
                Map.Entry::getValue, // this value needs to be a sum of the previous one.
                (k1, k2) -> k1));

关于如何解决这个问题有什么建议吗?我们的想法是拥有一个完整的流解决方案。

java dictionary sum hashmap java-stream
2个回答
1
投票

可能的解决方案之一是引入中间类来存储中间值(假设

Month
enum
):

private static Map<Month, Integer> sumGroupingByMonth(final Collection<Scooter> scooters) {
    @AllArgsConstructor
    final class Intermediate {
        final int newVal;
        final Day rentalDay;
    }

    return scooters.stream()
            .flatMap(scooter -> {
                final int newVal = scooter.getMileage() * scooter.getMileageRate();
                return scooter.getRentalDays()
                        .stream()
                        .map(day -> new Intermediate(newVal, day));
            })
            .collect(Collectors.groupingBy(intermediate -> intermediate.rentalDay.getMonth(), Collectors.summingInt(intermediate -> intermediate.newVal)));
}

我发现这段代码相当复杂:闭包、显式中间状态、函数作用域、中间对象,也许下面的代码可能更简单、更快?

private static int[] sumGroupingByMonth(final Iterable<Scooter> scooters) {
    final int[] data = new int[12];
    for ( final Scooter scooter : scooters ) {
        final int newVal = scooter.getMileage() * scooter.getMileageRate();
        for ( final Day rentalDay : scooter.getRentalDays() ) {
            data[rentalDay.getMonth().ordinal()] += newVal;
        }
    }
    return data;
}

0
投票

这是一个流等效项:

private static Map<Month, Integer> calculateByMonth(List<Scooter> scooters) {
    record MonthAndAmount(Month month, int amount) { }
    return scooters.stream()
            .flatMap(s -> s.getRentalDays().stream().map(d ->
                    new MonthAndAmount(
                            d.getMonth(),
                            s.getMileage() * s.getMileageRate())))
            .collect(Collectors.groupingBy(
                    MonthAndAmount::month,
                    Collectors.summingInt(MonthAndAmount::amount)));
}

这使用临时记录以及对

flatMap
的调用,将每辆踏板车内的每个租赁日转换为相应的月份和价值。 然后,它按月对值进行分组,对每个月内的值进行求和。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.