本系列文章译自Venkat Subramaniam的
Functional Programming in Java
未完待续,后续文章请继续关注[url={{ site.url }}]Java译站[/url]。
列出目录中的文件
用File类的list()方法可以很容易的列出目录中的所有文件的文件名。如果想要获取文件而不止是文件名的话,可以使用它的listFiles()方法。这很简单,难的是怎么去处理这个返回的列表。我们不再使用传统的冗长的外部迭代器,而是使用优雅的函数式来实遍历这个列表。这里我们还得用到JDK的新的CloseableStream接口以及一些相关的高阶函数。
下面这段代码可以列出当前目录下所有文件的名字。
Files.list(Paths.get("."))
.forEach(System.out::println);
如果想列出别的目录的话,可以把”.”替换成想要访问的目录的完整路径。
这里先是使用了Paths的get()方法,通过一个字符串创建了一个Path实例。然后通过Files工具类的list()方法获取到了一个ClosableStream对象,我们可以用它来遍历目录下的所有文件。然后我们使用内部迭代器forEach()来打印出文件名。我们先来看下这段代码的部分输出结果:列出当前目录下的文件及子目录。
./aSampleFiles.txt
./bin
./fpij
...
如果我们只想获取当前目录的子目录,而不要文件的话,可以使用filter()方法:
Files.list(Paths.get("."))
.filter(Files::isDirectory)
.forEach(System.out::println);
filter()方法将目录从文件流中筛选出来。我们把Files类的isDirectory方法的引用传了进去,而不是传递一个lambda表达式。回想下filter()方法它需要的是一个返回boolean值的Predicate类型,这个方法正好合适。最后我们用一个内部迭代器来打印出目录的名字。程序将会打印出当前目录的子目录。
./bin
./fpij
./output
...
这样写简单多了,跟Java老的写法相比省了不少代码。下面我们来看下如何列出匹配某个模式的文件。
列出目录下指定的文件
Java很早前就提供了一个list()方法的变种,用来筛选文件名。这个版本的list()方法接受一个FilenameFilter类型的参数。这个接口只有一个accept()方法,它接受两个参数:File dir(代表目录),以及String name(代表文件名)。accept()方法返回true的话这个文件名就会出现在返回的列表中,返回false则不在。我们来实现一下这个方法。
习惯性的做法是将一个实现了FilenameFilter接口的匿名内部类的实例传给list()方法。比如说,我们来看下如何用这种方式来返回fpij目录下的.java文件。
final String[] files =
new File("fpij").list(new java.io.FilenameFilter() {
public boolean accept(final File dir, final String name) {
return name.endsWith(".java");
}
});
System.out.println(files);
这着实得费些工夫写几行代码。这样的代码太聒噪了:创建对象,调用函数,定义匿名内部类,在类里面嵌入方法等等。我们不用再忍受这样的痛苦了,只需传一个接受两个参数并返回bollean的lambda表达式进去就好了。Java编译器会搞定剩下的事。
前面那个例子可以简单的用一个lambda表达式替换掉匿名内部就好了,但是还有进一步优化的空间。新的DirectoryStream工具可以帮助我们更高效的遍历大的目录结构。我们来试下这种方法。这是newDirectoryStream()方法的一个变种,它接受一个额外的过滤器。
Files.newDirectoryStream(
Paths.get("fpij"), path -> path.toString().endsWith(".java"))
.forEach(System.out::println);
这样我们去掉了匿名内部类并把繁琐的代码变得简洁明了。这两个版本的输出结果是一样的。我们来打印下指定的文件。
这段代码只会输出指定目录下的.java文件,下面是它的部分输出结果:
fpij/Compare.java
fpij/IterateString.java
fpij/ListDirs.java
...
我们基于文件名来筛选文件,同样也可以很容易通过文件属性,比如文件是不是可执行文件,是否可读,可写等来进行筛选。这么做的话得需要一个listFiles()方法,它接受一个FileFilter类型的参数。我们仍然使用lambda表达式来实现而不是去创建匿名内部类。现在来看一个列出当前目录下所有隐藏文件的例子。
final File[] files = new File(".").listFiles(file -> file.isHidden());
如果我们操作的是一个很大的目录,可以使用DirectoryStream而不是直接调用File上面的方法。
我们传给listFiles()方法的lambda表达式的签名和FileFilter接口的accept()方法的签名是一样的。这个lambda表达式接受的是一个File实例的参数,在这个例子中参数名是file。如果文件是隐藏属性的话,刚返回true,否则返回false.
这里其实还可以再精简下代码,我们不传lambda表达式了,传一个方法引用会让代码看起来会更简洁一些 :
new File(".").listFiles(File::isHidden);
我们先用lambda表达式实现,随后又使用方法引用将它重构得更加简洁。如果我们再写新的代码的话,当然应该采用这种简洁的方式。如果可以早点发现这种简洁的实现,我们当然要优先使用它。有一句话叫做”先让它能工作,然后再去优化(make it work, then make
it better)",先让代码能跑起来,等我们理清楚了,才去考虑简洁性和性能等进行优化。
我们通过一个例子来从目录中过滤出了指定的文件。下面我们来看下如何去遍历指定目录下的子目录。
未完待续,后续文章请继续关注
Java译站。
原创文章转载请注明出处:
http://it.deepinmind.com
分享到:
相关推荐
总的来说,Java函数式编程在遍历目录时提供了简洁、易读且高性能的解决方案。通过组合`Stream`操作,如`filter()`、`map()`和`forEach()`,开发者可以构建出强大的文件系统操作逻辑,同时保持代码的清晰和可维护性。...
Java函数式编程是一种编程范式,它强调使用函数和数据流来构造程序,而不是通过显式的控制流程。在Java中,函数式编程主要体现在Java 8及其后续版本引入的Lambda表达式和Stream API上。本篇文章关注的是如何在Java中...
Java函数式编程是一种编程范式,它强调使用函数作为程序的基本构建块,使得代码更加简洁、可读性强且易于测试。在Java 8及其后续版本中,函数式编程得到了广泛支持,引入了lambda表达式、函数式接口以及一系列用于...
7. **函数式编程**:Java 8引入了函数式编程的概念,如Lambda表达式和Stream API。虽然对于初级作业来说这可能不是必需的,但如果涉及,学生需要理解其简洁性和并行处理的优势。 8. **多线程**:Java提供了内置的多...
16. **Lambda表达式**:Java 8引入的新特性,用于简化函数式编程。 17. **Stream API**:高效处理集合数据,进行过滤、映射、归约等操作。 18. **日期时间API**:Java 8中的日期和时间API,如LocalDate, ...
许多现代编程语言如Haskell、Scala、F#、Clojure等完全支持或部分支持函数式编程,而像Java、C#和Python这样的传统面向对象语言也引入了对Lambda表达式和函数式编程特性的支持。 通过以上讨论,我们可以看到Lambda...
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,演示...
### Java编程核心知识点详解 #### 一、JDK主流版本的区别:从1.4到1.5 在Java的发展历程中,从1.4到1.5版本的跨越,标志着语言特性和性能的一次重大飞跃。Java 1.5,也被称为Java 5或Java SE 5.0,引入了一系列...
在 Scala 中,由于其与 Java 类似的面向对象特性,同时也支持函数式编程,这使得它成为开发复杂分布式系统和大数据处理应用的理想选择。 首先,让我们深入了解一下函数式编程的关键概念: 1. **纯函数**:纯函数是...
5. **改进的类型推断**:通过增强的类型推断,可以更方便地使用匿名内部类和Lambda表达式,为Java 8的函数式编程打下了基础。 6. **文件系统API**:Java 7引入了新的文件系统API(java.nio.file包),提供了更强大...
- **Python**: 可以使用`os`和`os.path`模块,如`os.walk()`函数用于递归遍历目录。 - **Java**: `java.io.File`类提供了`list()`, `listFiles()`, `listFiles(FileFilter)`等方法。 - **C++**: 使用`...
14. **Lambda表达式与函数式接口**:Java 8引入的新特性,简化代码编写,理解函数式编程的概念。 15. **集合接口与实现类**:List、Set、Queue、Map接口及其具体实现类的使用,如ArrayList与LinkedList的区别,...
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,...
用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:Java源码,初学实例,EJB实例 Message-Driven Bean EJB实例源代码,...
16. **Lambda表达式与函数式编程**:Java 8引入的新特性,简化代码,提高代码的可读性和效率。 17. **注解(Annotation)**:自定义注解,元注解,以及使用反射处理注解。 18. **模块化系统(Java 9+)**:理解...
9. **函数式编程**:Java 8引入了Lambda表达式和Stream API,学习如何使用这些新特性进行函数式编程,简化代码并提高效率。 10. **枚举与注解**:理解枚举类型的作用,以及注解(Annotation)在元编程中的应用。 ...
Java Stream 是 Java 8 引入的一个重要特性,它为处理集合数据提供了函数式编程的途径。Stream API 提供了一种高效且易于使用的处理数据的方式,例如,可以方便地进行过滤、映射、排序和聚合操作。在示例中,我们...
Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:...
11. **面向接口编程**:Java 8引入了默认方法和函数式编程的概念,教程可能也会涵盖这些现代Java特性。 12. **Java的异常和错误**:区分异常和错误,了解何时抛出异常,以及如何自定义异常。 13. **单元测试**:...
Java圆形电子时钟源代码 1个目标文件 内容索引:JAVA源码,系统相关,电子钟 用JAVA编写的指针式圆形电子钟,效果图如下所示,其实代码很简单,希望对你有帮助。 Message-Driven Bean EJB实例源代码 2个目标文件 摘要:...