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