【问题标题】:Filter more times in a Java 8 Stream在 Java 8 流中过滤更多次
【发布时间】:2017-10-16 22:01:56
【问题描述】:

是否可以在 Stream 中过滤更多次?例如,如果我有一个带有 ID 的列表,并且我想流式传输 HashMap 并将 HashMap 的键映射到列表中的键以及它们匹配的位置,我想从 HashMap 中获取对象并再次对其进行过滤,例如例如,该对象中大于 3 的 int 字段,最后将它们相加。例如,如果它找到了 10 种情况,其中列表的键和 HashMap 的键相等,它会过滤这 10 种情况并找到 3 种情况,例如 int 字段大于 3,它最终会返回这些情况的总和。

到目前为止,这是我的代码: 当我尝试打印结果列表时,我得到了这个: java.util.stream.ReferencePipeline$2@70177ecd

somemap.entrySet().stream().filter(e -> aListContainingIds.contains(e.getKey()))
            .map(Map.Entry::getValue)
            .map(n -> n.getTheOtherListFromMatchedValue().stream().filter(n -> n.getAnIntFieldFromObject() > 3))
            .collect(Collectors.toList());

【问题讨论】:

  • 你为什么不试试呢?
  • 我会说:是的,有可能 (ironie off) 向我们展示一些您尝试过的代码
  • 再用filter代替map。也可以尝试在嵌套谓词中使用allMatchanyMatch 而不是filter
  • 或者,由于您的问题远未明确,也许您想使用flatMap 而不是第二个map,在这种情况下,嵌套谓词中对filter 的调用将是正确。
  • 也许在你最后一个之前阅读 cmets 会有所帮助……

标签: list filter java-8 hashmap java-stream


【解决方案1】:

我认为你应该使用Stream.flatMaptoInt(或Stream.flatMaptoLong)而不仅仅是map

int total = somemap.entrySet().stream()
    .filter(e -> aListContainingIds.contains(e.getKey()))
    .map(Map.Entry::getValue)
    .flatMapToInt(value -> value.getTheOtherListFromMatchedValue().stream()) 
    .filter(n -> n.getAnIntFieldFromObject() > 3)
    .sum();

一般来说,flatMapToInt(或flatMap,如果流元素是某个类的实例而不是原语)将在您应用的函数返回另一个流时使用,并且您希望该流的元素成为原始流的一部分。

最后,你可以用IntStream.sum方法得到总数。

【讨论】:

  • 我认为,当您将.filter(…) 步骤移出flatMap 函数时,它会变得更容易阅读。没有功能上的区别,但是flatMap 函数适合一行,而随后的filter 不需要不同的缩进。
  • @Holger 好点,谢谢。但是,即使在并行 Stream 的情况下,您是否绝对确定没有区别?我的意思是,不仅是功能性的,而且关于流的展开方式
  • 如果有的话,我认为将filter 移动到外部流会更有效。最值得注意的是,如果您的谓词是一个捕获 lambda 表达式,则将其放在 flatMap 函数中将为每个外部流元素创建一个新实例,而将其放在外部流中将为整个操作创建一个谓词实例。当求和消费者与流实现中的过滤操作融合时,会产生类似的效果。我并不是说效果会很明显……
  • @Holger 谢谢
猜你喜欢
  • 2018-12-17
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2015-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多