【问题标题】:Java 8 Stream + Map + ForEach + CollectJava 8 流 + 地图 + ForEach + 收集
【发布时间】:2017-01-16 02:28:29
【问题描述】:

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

List<String> fields = Utils.readFile("myText.txt", true);

一旦我得到这个List&lt;String&gt;,我想遍历这个列表并将每个值传递给一个使用这个值的函数,查询数据库并准备一个List&lt;MyCustomObject&gt;并返回相同的值。

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

我已经尝试了以下 -

Utils.readFile("myText-"+".txt", true)
        .stream()
        .map(str -> getListOfCustomObjForEachStr(str, pstmt))
        .collect(Collectors.toList());

但它返回一个List&lt;List&lt;MyCustomObject&gt;&gt; 而不是合并的List&lt;MyCustomObject&gt;

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

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

编辑 1 使用 FlatMap 实现了如下所示 - 请建议是否有其他更好的方法。希望有一天它对某个地方的人有所帮助:) 继续分享。

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

【问题讨论】:

  • 我猜'getListOfCustomObjForEachStr(str, pstmt)' 返回一个List,这就是你得到一个列表的原因。如果你的 map 函数只能返回一个对象,那么你就可以了。
  • @JamesBlack :但在 DB 中,我有一个针对每个输入字符串的值列表。因此,我必须协作/合并各个列表并准备最终列表。这就是 getListOfCustomObjForEachStr 返回 List 而不是 MyCustomObject 的原因。我希望你能理解我的担忧。让我知道否则会尝试重新构建它。
  • @SwapnilJaju flatMap(),正如您在问题中添加到您的编辑,如果您想将列表扁平化为一个,那么这是一种方法。
  • flatMap 如果您不需要中间结果(如List&lt;List&lt;String&gt;&gt;)。否则,如果您需要它们,您仍然可以在之后致电reduce。顺便问一下:你知道Files.lines 了吗?它返回 Stream&lt;String&gt; 的行数。
  • @Magnilex:感谢您的评论。

标签: java lambda java-8 java-stream


【解决方案1】:

使用flatMap 是获取平面列表的规范方法。你可以用一个步骤代替map+flatMap

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

您可能会首先考虑返回StreamgetListOfCustomObjForEachStr 的替代方法。此外,不存在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&lt;MyCustomObjects&gt;s 添加到结果List&lt;MyCustomObjects&gt;


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

【讨论】:

  • 霍尔格:感谢您的建议。您能否指出哪种方法更好?使用 flatMap+Collect(Collectors.toList()) 或 map+Collect(ArrayList::new, List::addAll, List::addAll)
  • 对于这种特定情况和当前的 Java 版本,第二个变体可能有更好的性能,但第一个变体是通用模式,在解决第二个变体的类似任务时也可以应用解决不了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2022-06-18
  • 1970-01-01
相关资源
最近更新 更多