Java函数式编程(十一):遍历目录

 更新时间:2014年09月26日 09:34:40   作者:有孚  
这篇文章主要介绍了Java函数式编程(十一):遍历目录,本文是系列文章的第11篇,其它文章请参阅本文底部的相关文章,需要的朋友可以参考下
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

列出目录中的文件

用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);

ilter()方法将目录从文件流中筛选出来。我们把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)",先让代码能跑起来,等我们理清楚了,才去考虑简洁性和性能等进行优化。

我们通过一个例子来从目录中过滤出了指定的文件。下面我们来看下如何去遍历指定目录下的子目录。

相关文章

  • 深入学习JavaWeb中监听器(Listener)的使用方法

    深入学习JavaWeb中监听器(Listener)的使用方法

    这篇文章主要为大家详细介绍了深入学习JavaWeb中监听器(Listener)的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-09-09
  • Java中父类怎么调用子类的方法

    Java中父类怎么调用子类的方法

    这篇文章主要介绍了Java父类调用子类的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • 关于SpringBoot使用Redis空指针的问题(不能成功注入的问题)

    关于SpringBoot使用Redis空指针的问题(不能成功注入的问题)

    这篇文章主要介绍了关于SpringBoot使用Redis空指针的问题(不能成功注入的问题),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Java框架MyBatis接口编程过程解析

    Java框架MyBatis接口编程过程解析

    这篇文章主要介绍了Java框架MyBatis接口编程过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java的synchronized关键字深入解析

    Java的synchronized关键字深入解析

    这篇文章主要介绍了Java的synchronized关键字深入解析,在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,需要的朋友可以参考下
    2023-12-12
  • Java实现多线程文件下载的代码示例

    Java实现多线程文件下载的代码示例

    本篇文章主要介绍了Java实现多线程下载的代码示例,Java多线程可以充分利用CPU的资源,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • Java非阻塞I/O模型之NIO相关知识总结

    Java非阻塞I/O模型之NIO相关知识总结

    在了解NIO (Non-Block I/O) 非阻塞I/O模型之前,我们可以先了解一下原始的BIO(Block I/O) 阻塞I/O模型,NIO模型能够以非阻塞的方式更好的利用服务器资源,需要的朋友可以参考下
    2021-05-05
  • Java在PowerPoint中添加上标和下标的实现方法

    Java在PowerPoint中添加上标和下标的实现方法

    当我们在演示文稿中添加商标、版权或其他符号时,我们可能希望该符号出现在某个文本的上方或下方。在Microsoft PowerPoint中,我们可以通过对符号应用上标或下标格式来实现这种效果,这篇文章主要介绍了Java在PowerPoint中添加上标和下标,需要的朋友可以参考下
    2022-10-10
  • jpa?EntityManager?复杂查询实例

    jpa?EntityManager?复杂查询实例

    这篇文章主要介绍了jpa?EntityManager?复杂查询实例,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • Java 判断一个时间是否在另一个时间段内

    Java 判断一个时间是否在另一个时间段内

    这篇文章主要介绍了Java 判断一个时间是否在另一个时间段内的相关资料,需要的朋友可以参考下
    2016-10-10

最新评论

?


http://www.vxiaotou.com