java 8 减少累加器 return 类型
java 8 reduce accumulator return type
我需要对一个元素列表进行简单的遍历,对所有元素进行某种转换,然后将所有结果累积到一个列表中。
像这样:
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 的第二个参数应该 return 一个 List 但它 return 是一个布尔值,它是 addAll 方法的 return 类型。
当然可以这样:
List<GraphEdge> edges = graphResults.stream().
map(res -> resultToEdges(res)).
reduce(new LinkedList<GraphEdge>(), (list, res) ->
{ list.addAll(res); return list; });
但它并不那么优雅。
还有其他方法吗?
无需使用reduce
。
List<GraphEdge> edges = graphResults.stream().
flatMap(res -> resultToEdges(res).stream()).
collect(Collectors.toList());
这是假设 resultToEdges(res)
returns GraphEdge
的列表(或其他一些集合),这似乎是这种情况。
对这种事情使用 reduce 无论如何都是错误的(参见 )。但是,您可以使用 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
只是一个map后面进行了扁平化操作(不足为奇),例如:
[[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]
在函数式语言中,经常有不可变列表和函数 appends/concats 和 returns 一个新的不可变列表。那会给你一个 lambda 中的单行解决方案。唉Java没有这样的方法..
正如已经指出的那样,没有必要减少。如果您想要 LinkedList
作为返回值,您可以使用:
List<GraphEdge> edges = graphResults.stream()
.flatMap(res -> resultToEdges(res).stream())
.collect(toCollection(LinkedList::new));
不要使用 reduce
进行可变缩减。这不仅不雅。这是错误的,如果流是并行的,将无法正常工作。要么按照其他答案的建议使用 flatMap
,要么使用类似于 reduce
但设计用于可变累加器的 collect
的 3 参数版本:
List<GraphEdge> edges = graphResults.stream()
.map(res -> resultToEdges(res))
.collect(LinkedList::new, LinkedList::addAll, LinkedList::addAll);
我需要对一个元素列表进行简单的遍历,对所有元素进行某种转换,然后将所有结果累积到一个列表中。 像这样:
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 的第二个参数应该 return 一个 List 但它 return 是一个布尔值,它是 addAll 方法的 return 类型。
当然可以这样:
List<GraphEdge> edges = graphResults.stream().
map(res -> resultToEdges(res)).
reduce(new LinkedList<GraphEdge>(), (list, res) ->
{ list.addAll(res); return list; });
但它并不那么优雅。 还有其他方法吗?
无需使用reduce
。
List<GraphEdge> edges = graphResults.stream().
flatMap(res -> resultToEdges(res).stream()).
collect(Collectors.toList());
这是假设 resultToEdges(res)
returns GraphEdge
的列表(或其他一些集合),这似乎是这种情况。
对这种事情使用 reduce 无论如何都是错误的(参见 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
只是一个map后面进行了扁平化操作(不足为奇),例如:
[[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]
在函数式语言中,经常有不可变列表和函数 appends/concats 和 returns 一个新的不可变列表。那会给你一个 lambda 中的单行解决方案。唉Java没有这样的方法..
正如已经指出的那样,没有必要减少。如果您想要 LinkedList
作为返回值,您可以使用:
List<GraphEdge> edges = graphResults.stream()
.flatMap(res -> resultToEdges(res).stream())
.collect(toCollection(LinkedList::new));
不要使用 reduce
进行可变缩减。这不仅不雅。这是错误的,如果流是并行的,将无法正常工作。要么按照其他答案的建议使用 flatMap
,要么使用类似于 reduce
但设计用于可变累加器的 collect
的 3 参数版本:
List<GraphEdge> edges = graphResults.stream()
.map(res -> resultToEdges(res))
.collect(LinkedList::new, LinkedList::addAll, LinkedList::addAll);