java 8减少累加器返回类型

时间:2015-03-16 11:28:13

标签: java dictionary lambda java-8 reduce

我需要对元素列表进行简单的遍历,对所有元素执行某种转换,然后将所有结果累积到列表中。 像这样:

List<GraphEdge> edges = new LinkedList<GraphEdge>();
for (CrawlResult result : crawlResults) {
    edges.addAll(resultToEdges(result));
}

这段代码需要4行,没有什么能比让我在一行中更快乐。因此,java 8流(map + reduce)用于救援。

我尝试使用以下行:

List<GraphEdge> edges = graphResults.stream().
        map(res -> resultToEdges(res)).
        reduce(new LinkedList<GraphEdge>(), (list, res) -> list.addAll(res));

它没有通过编译,因为reduce的第二个参数应返回一个List,但它返回一个布尔值,这是addAll方法的返回类型。

当然,这种方式可行:

List<GraphEdge> edges = graphResults.stream().
                map(res -> resultToEdges(res)).
                reduce(new LinkedList<GraphEdge>(), (list, res) -> 
                { list.addAll(res); return list; });

但它并不那么优雅。 还有其他任何方式吗?

5 个答案:

答案 0 :(得分:6)

无论如何,使用reduce来处理这类事情是错误的(参见this thread)。但是,您可以使用flatMap代替map,并将最终Stream收集到List中:

List<GraphEdge> edges = graphResults.stream()
        .flatMap(res -> resultToEdges(res).stream())
        .collect(toList()); //or toCollection with a concrete implementation, you can check the docs

flatMap只是一张地图,后面是展平操作(并不奇怪),例如:

[[1, 2], [3, 4]].flatMap(x -> x.add(5)) //imagine that add returns a list 

将首先应用映射:

[[1, 2, 5], [3, 4, 5]]

然后展平列表,以便获得:

[1, 2, 5, 3, 4, 5]

答案 1 :(得分:5)

无需使用reduce

List<GraphEdge> edges = graphResults.stream().
    flatMap(res -> resultToEdges(res).stream()).
    collect(Collectors.toList());

这假设resultToEdges(res)返回GraphEdge的List(或其他一些Collection),这似乎是这种情况。

答案 2 :(得分:3)

不要使用reduce进行可变缩减。它不仅不优雅。这是错误的,如果流是并行的,它将无法正常工作。使用flatMap作为其他答案建议,或者collect的3参数版本与reduce类似,但设计用于可变累加器:

List<GraphEdge> edges = graphResults.stream()
    .map(res -> resultToEdges(res))
    .collect(LinkedList::new, LinkedList::addAll, LinkedList::addAll);

答案 3 :(得分:2)

正如已经指出的那样,没有必要减少。如果您想要LinkedList作为返回值,可以使用:

List<GraphEdge> edges = graphResults.stream()
    .flatMap(res -> resultToEdges(res).stream())
    .collect(toCollection(LinkedList::new));

答案 4 :(得分:0)

在函数式语言中,通常有不可变的列表和函数,它们会追加/连接并返回一个新的不可变List。那会给你一个lambda的单线解决方案。 Alas Java没有这样的方法..