Java 8特性尝鲜:新新IO
在这个专题前面的文章中,我们已经看到,使用Java8的lambda表达式对现有的JDK1.2 I/O库的提升,主要是可以使用lambda表达式来构造java.io.FileFilter的实例。
很多读者都指出了,java.io中的很多API已经被Java7中的java.nio的API所取代了,这里N的意思是New。然而Java8还给我们带来了更多的惊喜,我们把它叫做新新IO(New New IO),虽然jOOQ社区的成员都建议把它叫做企业级IO(Enterprise IO)。
言归正传,我们对Java8的新IO特性已经有了一个初步的了解。我们先来看一下java.nio.Files里面的增加的新的方法。最给力的一点是我们终于可以方便的列出路径下的文件了,Java8里面我们只需要用一下这个新加的方法Files.list(),这个返回的是一个惰性的文件流:
Files.list(new File(".").toPath()) .forEach(System.out::println);
这个的输出结果是:
.\.gitignore .\.idea .\java8-goodies.iml .\LICENSE.txt .\pom.xml .\README.txt .\src .\target
需要注意的是forEach方法是一个“最终方法”,也就是最终消费这个流的。别人就不能再使用这个流了。
如果我们想过滤掉所有的隐藏文件并只显示前三个普通文件的话,可以这么写:
Files.list(new File(".").toPath()) .filter(p -> !p.getFileName() .toString().startsWith(".")) .limit(3) .forEach(System.out::println);
新的输出会是这样:
.\java8-goodies.iml .\LICENSE.txt .\pom.xml
现在看起来已经很棒了。还能再给力点么?当然。你可以使用新的Files.walk()方法遍历整个目录。下面是代码示例:
Files.walk(new File(".").toPath()) .filter(p -> !p.getFileName() .toString().startsWith(".")) .forEach(System.out::println);
问题来了,上面的代码会创建一个路径流,过滤掉了所有的隐藏文件和目录,但是它们的子文件还是会被列出来。因此会得到这样的结果:
过滤的: .\.git 不过却列出了: .git\COMMIT_EDITMSG .\.git\config .\.git\description [...]
不难理解,Files.walk()返回了所有子文件的流,filter方法会将所有隐藏文件删除掉,不过现在walk的实现里对递归下去的文件不起任何作用。这确实让人有点失望。我们也没法借助Java7里面的walkFileTree方法,因为它接受的参数FileVisitor类型不是一个@FunctionalInterface。
不过,通过点小的改进可以勉强解决下这个问题:
Files.walk(new File(".").toPath()) .filter(p -> !p.toString() .contains(File.separator + ".")) .forEach(System.out::println);
现在可以得到我们想要的结果了:
. .\java8-goodies.iml .\LICENSE.txt .\pom.xml .\README.txt .\src .\src\main .\src\main\java .\src\main\java\org .\src\main\java\org\jooq [...]
同样给我们带来惊喜的是Files.lines方法。下面的代码展示了如何使用它方便的换行读取文件,并逐行trim同时过滤空白行:
Files.lines(new File("pom.xml").toPath()) .map(s -> s.trim()) .filter(s -> !s.isEmpty()) .forEach(System.out::println);
输出的结果:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.jooq</groupId> <artifactId>java8-goodies</artifactId> <version>1.0-SNAPSHOT</version> [...]
总结
惰性求值这个概念会让很多人摸不着头脑,同样的还有流只能消费一次这个情况。我敢打赌Java 8的IO流相关API的问题会是Stack Overflow的新宠。
尽管如此,不得不说Stream API的确是非常酷。在下期的文章里面,我们将会介绍如何使用lambda表达式和流来进行排序,再后面要亮相的将是Java8给DB操作带来的提升。
原文地址:http://it.deepinmind.com/java/2014/02/13/Java8-features-new-new-io.html