我可以使用Java流收集器来实现这种行为吗
我有一个包含以下代码的小方法:我可以使用Java流收集器来实现这种行为吗,java,java-stream,collectors,Java,Java Stream,Collectors,我有一个包含以下代码的小方法: final int year = getYear(); final Carrier carrier = getCarrier(); final CarrierMetrics metrics = new CarrierMetrics(carrier); repository.getFlightStream(year) .filter(flight -> flight.getCarrier().equals(carrier))
final int year = getYear();
final Carrier carrier = getCarrier();
final CarrierMetrics metrics = new CarrierMetrics(carrier);
repository.getFlightStream(year)
.filter(flight -> flight.getCarrier().equals(carrier))
.forEach(flight -> {
metrics.addFlight(flight);
printf("%,10d\t%,10d\t%,10d\t%,10d\r",
metrics.getTotalFlights(),
metrics.getTotalCancelled(),
metrics.getTotalDiverted(),
metrics.getAirports().size()
);
});
希望很明显,我所做的是在处理流中的每个航班时积累度量。代码确实有效,但我想知道是否有更好的(功能更强大的)方法来实现此行为,可能是使用收集器。任何反馈都将不胜感激
谢谢
-Tony如果
CarrierMetrics
公开addAll(列出航班)
方法,则可以执行以下操作:
List<Flight> flights = repository.getFlightStream(year)
.filter(flight -> flight.getCarrier().equals(carrier))
.collect(Collectors.toList());
metrics.addAll(flights);
List flights=repository.getFlightStream(年)
.filter(flight->flight.getCarrier().equals(carrier))
.collect(Collectors.toList());
metrics.addAll(航班);
如果CarrierMetrics
公开添加所有(列出航班)
方法,则可以执行以下操作:
List<Flight> flights = repository.getFlightStream(year)
.filter(flight -> flight.getCarrier().equals(carrier))
.collect(Collectors.toList());
metrics.addAll(flights);
List flights=repository.getFlightStream(年)
.filter(flight->flight.getCarrier().equals(carrier))
.collect(Collectors.toList());
metrics.addAll(航班);
如果在forEach
中打印很重要,
那么您当前的解决方案就是这样。
forEach
专为副作用设计,
还有两个副作用:将度量添加到CarrierMetrics
实例和打印
如果
forEach
中的打印仅用于调试,
而不是在你的最终解决方案中,
然后,一个更实用的实现是将结果直接收集到CarrierMetrics
实例中,
而不是先初始化实例,然后使用forEach
手动添加。
可以使用的重载包含3个参数:
- A
创建初始Supplier
实例,该实例将用作累加器CarrierMetrics
- 将
实例传递给累加器的Flight
BiConsumer
- 类型
只是基于您共享的代码的猜测。它是流的类型(以及Flight
method的参数类型)CarrierMetrics.addFlight
- 类型
- 一种在平行流情况下组合多个累加器的
双累加器
final int year = getYear();
final CarrierMetrics metrics = repository.getFlightStream(year)
.filter(flight -> flight.getCarrier().equals(carrier))
.collect(CarrierMetrics::new, CarrierMetrics::addFlight, (a1, a2) -> {});
第三个参数,组合器,是一个伪参数,
你需要解决这个问题。
它的实现应该将两个CarrierMetrics
参数组合到第一个参数中。
(我不能给出一个具体的例子,因为您没有分享足够的有关CarrierMetrics
的详细信息,因此无法了解如何做。
但举个例子,如果是列表
累加器,
实现可以是(a1,a2)->a1.addAll(a2)
)
(最后,本例假设CarrierMetrics
具有无参数构造函数,以便CarrierMetrics::new
引用起作用。
如果没有这样的构造函数,您可以使用适当的lambda表达式,例如
()->new carriermics(…)
)如果在forEach
中打印很重要,
那么您当前的解决方案就是这样。
forEach
专为副作用设计,
还有两个副作用:将度量添加到CarrierMetrics
实例和打印
如果
forEach
中的打印仅用于调试,
而不是在你的最终解决方案中,
然后,一个更实用的实现是将结果直接收集到CarrierMetrics
实例中,
而不是先初始化实例,然后使用forEach
手动添加。
可以使用的重载包含3个参数:
- A
创建初始Supplier
实例,该实例将用作累加器CarrierMetrics
- 将
实例传递给累加器的Flight
BiConsumer
- 类型
只是基于您共享的代码的猜测。它是流的类型(以及Flight
method的参数类型)CarrierMetrics.addFlight
- 类型
- 一种在平行流情况下组合多个累加器的
双累加器
final int year = getYear();
final CarrierMetrics metrics = repository.getFlightStream(year)
.filter(flight -> flight.getCarrier().equals(carrier))
.collect(CarrierMetrics::new, CarrierMetrics::addFlight, (a1, a2) -> {});
第三个参数,组合器,是一个伪参数,
你需要解决这个问题。
它的实现应该将两个CarrierMetrics
参数组合到第一个参数中。
(我不能给出一个具体的例子,因为您没有分享足够的有关CarrierMetrics
的详细信息,因此无法了解如何做。
但举个例子,如果是列表
累加器,
实现可以是(a1,a2)->a1.addAll(a2)
)
(最后,本例假设CarrierMetrics
具有无参数构造函数,以便CarrierMetrics::new
引用起作用。
如果没有这样的构造函数,您可以使用适当的lambda表达式,例如
()->new carriermics(…)
)使用Collector.of
来定义自定义收集器。您的peek().allMatch()是一种非常复杂的forEach()方法。是的,这是收集器的工作。但您也可以使用这个collect()方法:同意关于使用forEach而不是peek的评论。代码相应更新。使用Collector.of
定义自定义收集器。您的peek().allMatch()是一种非常复杂的forEach()方法。是的,这是收集器的工作。但您也可以使用这个collect()方法:同意关于使用forEach而不是peek的评论。代码相应更新。此特定方法在更新度量值时打印度量值,因此等待度量值全部累积似乎没有意义。@TonyPiazza您的意思是,您确实希望在收集度量值时打印度量值的每个变化?这不仅仅是为了调试?为什么这么做?我想完全一样@JBNizet@Gal这就是说,将所有航班收集到内存中的列表是浪费的,需要两次通行证,并且不允许