【问题标题】:Why is Java8 flatmap returning a List of List?为什么 Java8 flatmap 返回列表列表?
【发布时间】:2015-04-20 14:18:14
【问题描述】:

我试图使用以下 java 8 代码将 List 的函数“应用”到 ListFile 对象。

List<Function<File, String>> mappingFunctions = Arrays.asList(
    (file) -> file.getName(),
    (file) -> file.getPath(),
    (file) -> ((Long) file.length()).toString(),
    (file) -> file.isDirectory() ? "Directory" : "File"
);

// collects all files in this and one level down directory
List<File> files =
    Stream.of(new File(".").listFiles())
          .flatMap(file -> file.listFiles() == null ? Stream.of(file) : Stream.of(file.listFiles()))
          .collect(toList());

System.out.println("All the files gathered ...\n");
files.forEach(System.out::println);
System.out.println("\nApplying the list of functions to all the files gathered ...\n");
files.stream()
     .flatMap(file -> Stream.of(mappingFunctions.stream()
                                                .map((func) -> func.apply(file))
                                                .collect(Collectors.toList())))
     .forEach(System.out::println);

我得到的输出如下,

All the files gathered ...

.\.idea\compiler.xml
.\.idea\copyright
.\.idea\description.html
.\.idea\dictionaries
.\.idea\encodings.xml
.\.idea\misc.xml
.\.idea\modules.xml
.\.idea\project-template.xml
.\.idea\scopes
.\.idea\uiDesigner.xml
.\.idea\vcs.xml
.\.idea\workspace.xml
.\out\production
.\src\com
.\Test.iml

将函数列表应用于所有收集的文件...

[compiler.xml, .\.idea\compiler.xml, 739, File]
[copyright, .\.idea\copyright, 0, Directory]
[description.html, .\.idea\description.html, 97, File]
[dictionaries, .\.idea\dictionaries, 0, Directory]
[encodings.xml, .\.idea\encodings.xml, 164, File]
[misc.xml, .\.idea\misc.xml, 525, File]
[modules.xml, .\.idea\modules.xml, 255, File]
[project-template.xml, .\.idea\project-template.xml, 91, File]
[scopes, .\.idea\scopes, 0, Directory]
[uiDesigner.xml, .\.idea\uiDesigner.xml, 8792, File]
[vcs.xml, .\.idea\vcs.xml, 164, File]
[workspace.xml, .\.idea\workspace.xml, 28470, File]
[production, .\out\production, 0, Directory]
[com, .\src\com, 0, Directory]
[Test.iml, .\Test.iml, 437, File]

问题 1:为什么我在第二个输出中得到一个列表列表,而在第一个输出中只有一个列表?他们都在集合流上使用平面地图。

问题 2:有没有更好的方法在 Java 8 中实现同样的功能?

【问题讨论】:

    标签: java lambda java-8 java-stream flatmap


    【解决方案1】:

    在第二种情况下,flatMap 方法生成了一个 Stream&lt;List&lt;String&gt;&gt;,其单个元素是 List&lt;String&gt;

    在第一种情况下,flatMap 方法生成单个 FileStream&lt;File&gt;Files 数组的 Stream&lt;File&gt;

    注意有两个Stream.of 方法:

    接受一个类型为 T 的数组(或可变数量的 T 参数)并产生一个 T 流:

    of(T... values)
    

    写的时候用这个方法:

    .flatMap(file -> Stream.of(file.listFiles()))
    

    另一个接受单个 T 并生成带有单个元素 T 的 Stream:

    of(T t)
    

    写的时候用这个方法:

    .flatMap(file -> Stream.of(.. some expression that produces a List ..))
    

    如果您希望您的最终流处理生成单个字符串流:

    files.stream()
            .flatMap(file ->  mappingFunctions.stream()
                                              .map((func) -> func.apply(file)))
            .forEach(System.out::println);
    

    这样,flatMap 中的 lambda 表达式将生成 Stream&lt;String&gt;flatMap 会将这些 Streams 扁平化为单个 Stream&lt;String&gt;

    【讨论】:

    • 是的,这正是我想要了解的。在第二种情况下,元素如何转换为字符串列表。我期待一个字符串列表,而我得到了一个字符串列表。有没有详细的解释我可以在某个地方找到?
    • @MadhurBansal 您可以删除.collect(Collectors.toList())Stream.of (..),flatMap 将返回Stream&lt;String&gt; 而不是Stream&lt;List&gt;。我会编辑答案。
    • @MadhurBansal 查看我的编辑。解释是 Stream.of(List) 生成带有单个元素的 Stream&lt;List&lt;String&gt;&gt;,而不是您预期的 Stream&lt;String&gt;
    • 哦,好的,现在知道了 - 非常感谢 Eran。列表参数未被 Stream.of 识别为可变参数!您提出的解决方案有效。
    猜你喜欢
    • 2019-12-20
    • 1970-01-01
    • 2019-05-22
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多