我可以使用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
      只是基于您共享的代码的猜测。它是流的类型(以及
      CarrierMetrics.addFlight
      method的参数类型)
  • 一种在平行流情况下组合多个累加器的
    双累加器
像这样:

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
      只是基于您共享的代码的猜测。它是流的类型(以及
      CarrierMetrics.addFlight
      method的参数类型)
  • 一种在平行流情况下组合多个累加器的
    双累加器
像这样:

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这就是说,将所有航班收集到内存中的列表是浪费的,需要两次通行证,并且不允许