Java 8 Stream + Map + ForEach + Collect

时间:2017-01-16 02:28:29

标签: lambda java-8 java-stream

我正在从文件中读取值并获取列表。 如下 -

findAllByState()

一旦我得到这个List<String> fields = Utils.readFile("myText.txt", true); ,我想迭代这个列表并将每个值传递给一个使用该值的函数,查询到DB并准备一个List<String>并返回相同的内容。

在Java 7中实现非常简单,但我无法使用Stream + Map / forEach + Collect操作在Java 8中实现它。

我已经尝试了下面的内容 -

List<MyCustomObject>

但它会返回Utils.readFile("myText-"+".txt", true) .stream() .map(str -> getListOfCustomObjForEachStr(str, pstmt)) .collect(Collectors.toList()); 而不是合并List<List<MyCustomObject>>

getListOfCustomObjForEachStr()方法为上面代码中传递的每个输入str返回一个List。我需要一个合并的列表

有人可以指导我在这里可以做些什么来获得合并列表吗? (我是Java 8的新手所以它看起来似乎是个愚蠢的问题,但感谢任何帮助)

修改1 使用FlatMap实现如下所示 - 请建议是否有其他更好的方法来做到这一点。希望有一天能帮到某个人的某个地方:)继续分享。

List<MyCustomObject>

1 个答案:

答案 0 :(得分:8)

使用flatMap是获取平面列表的规范方法。您可以使用单步而不是map + flatMap

List<MyCustomObjects> list = Utils.readFile("myText-"+".txt", true)
    .stream()
    .flatMap(str -> getListOfCustomObjForEachStr(str, pstmt).stream())
    .collect(Collectors.toList());

您可能会想到getListOfCustomObjForEachStr首先返回Stream的替代方案。此外,不存在Files.lines,它返回行字符串流而不先填充临时List

在这种特定情况下,还有另一种选择。考虑到.collect(Collectors.toList())等同于.collect(ArrayList::new, List::add, List::addAll)¹,您也可以使用

List<MyCustomObjects> list = Utils.readFile("myText-"+".txt", true)
    .stream()
    .map(str -> getListOfCustomObjForEachStr(str, pstmt))
    .collect(ArrayList::new, List::addAll, List::addAll);

add替换为addAll,这已足以将所有子List<MyCustomObjects>添加到结果List<MyCustomObjects>

¹这就是toList()现在的工作方式,但由于未指定这样做,因此在其他版本中可能会有所不同