将带有内部迭代器的增强循环转换为流
Convert enhance loop with inner iterator to stream
我正在尝试将他的一段工作代码转换成一个流:
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));
关于如何解决这个问题有什么建议吗?这个想法是有一个完整的流解决方案。
一种可能的解决方案是引入一个中间值 class 来存储中间值(假设 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;
}
我正在尝试将他的一段工作代码转换成一个流:
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));
关于如何解决这个问题有什么建议吗?这个想法是有一个完整的流解决方案。
一种可能的解决方案是引入一个中间值 class 来存储中间值(假设 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;
}