如何计算流过滤器上的匹配?

mem*_*und 14 java java-8 java-stream

如何计算流过滤器的匹配?我正在尝试将以下代码重构为java8 stream:

//java7
int i = 0;
for (Node node : response.getNodes()) {
    Integer id = node.getId();
    if (id != null) {
        node.setContent("This is the id: " + id);
        i++;
    }
}

//java8
response.getNodes().stream()
    .filter(node -> node.getId() != null)
    .forEach(node -> node.setValue("This is the id: " + node.getId()));
Run Code Online (Sandbox Code Playgroud)

我现在如何获得已应用的已过滤元素的数量?Sidequestion:在旧代码中我可以Integer id多次重复使用.如何使用流实现相同的功能?

Ale*_* C. 21

由于setValue是副作用功能,您可以使用peek:

long i = response.getNodes()
                 .stream()
                 .filter(node -> node.getId() != null)
                 .peek(node -> node.setValue("This is the id: " + node.getId()))
                 .count();
Run Code Online (Sandbox Code Playgroud)

我不是这种方法的粉丝,因为峰值用于调试目的(这可以解决问题).请注意,在Java 9中,count()如果可以直接从源计算计数,则可能无法执行流管道(我不认为这是这种情况,因为您应用了过滤,但最好记住它) .

Sidequestion:在旧代码中,我可以多次重用Integer id.如何使用流实现相同的功能?

这取决于你的用例,因为API没有元组,你最好的机会就是创建一个类Tuple2,这样你就可以将每个节点映射到一个新的元组并重用id.

就像是:

.stream().map(node -> new Tuple2<>(node, node.getId()).moreStreamOps(...);
                                                      ^
                                                      |
                 at that point you have a Stream<Tuple2<Node, Integer>> 
                 from which you can grab the id with Tuple2#getSecond
Run Code Online (Sandbox Code Playgroud)

在您的情况下,如果您使用节点流,您可以随时获取ID getId().

  • @membersound好吧,如果你知道你在做什么,这不是问题.你无法总是避免副作用,因为Java无论如何都不是一种功能语言(即使有一堆新功能). (3认同)
  • @ isnot2bad是的,这是我通常做/推荐的,如果你需要2个终端操作(并且性能不是一个问题,也不是你需要优化的东西),但在这种情况下,`forEach`可能与` peek`,所以一次通过就可以了. (3认同)
  • 您可以将任务拆分为两个不同的流操作:第一个使用forEach()设置id,第二个使用count()计算节点. (2认同)