为什么Java8 flatmap返回List列表?

时间:2015-02-19 09:40:10

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

我尝试使用以下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:为什么我在第二个输出中得到列表列表而第一个列表中只有一个列表?它们都使用flatmap而不是集合流。

问题2:在Java 8中是否有更好的方法来实现相同的目标?

1 个答案:

答案 0 :(得分:1)

在第二种情况下,flatMap方法产生了Stream<List<String>>,其单个元素为List<String>

在第一种情况下,flatMap方法生成Stream<File>FileStream<File>数组File

请注意,有两种Stream.of方法:

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

of(T... values)

编写时使用此方法:

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

另一个接受单个T并产生一个具有单个元素T的流:

of(T t)

编写时使用此方法:

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

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

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

这样,flatMap中的lambda表达式将生成Stream<String>,而flatMap会将Stream展平为单个Stream<String>