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

列出目录中的文件

用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)",先让代码能跑起来,等我们理清楚了,才去考虑简洁性和性能等进行优化。

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

(0)

相关推荐

  • Java使用File类遍历目录及文件实例代码

    1. 构造函数 File(String args0)//使用一个表示文件或目录的路径的字符串创建一个File对象 File(URL args0)//使用一个URL对象创建File对象 File(File args0, String args1)//使用一个File对象(一般是目录)和一个文件名字符串创建File对象 File(String args0, String args1)//使用一个目录字符串和一个文件名字符串创建对象 使用File类需要注意两点: 第一,File类用于表示文件或目录的名

  • Java文件操作之按行读取文件和遍历目录的方法

    按行读取文件 package test; import java.io.*; import java.util.*; public class ReadTest { public static List<String> first_list; public static List<String> second_list; public ReadTest() { first_list = new LinkedList<>(); second_list = new Link

  • java 对文件夹目录进行深度遍历实例代码

    java 对文件夹目录进行深度遍历实例代码 1.题目 对指定目录进行所有内容的列出(包含子目录中的内容),也可以理解为对目录进行深度遍历. 2.解题思想 从电脑中获取文件目录,建立函数对其遍历,在这个函数中需要对该目录中的每个文件进行判断,如果文件还是目录,则调用函数本身继续对其进行遍历,如果文件不是目录,则直接输出文件名.为了加强显示的效果,我们还可以建立一个getSpace函数,对其进行缩进. 需要注意的是,不要直接遍历C盘的内容,其目录层次太深,含有太多的系统级文件,容易返回为空,导致空指

  • Java遍历输出指定目录、树形结构所有文件包括子目录下的文件

    下面通过一段代码介绍下Java输出指定目录.树形结构下的所有文件包括子目录中的文件的方法,并附有效果图. import java.io.File; public class ReadDirectory { // 文件所在的层数 private int fileLevel; /** * 生成输出格式 * @param name 输出的文件名或目录名 * @param level 输出的文件名或者目录名所在的层次 * @return 输出的字符串 */ public String createPri

  • java使用iterator遍历指定目录示例分享

    可以遍历指定目录(一个或多个)及其所有子文件,用Iterator实现 复制代码 代码如下: package archiver.util; import java.io.File;import java.util.ArrayList;import java.util.Arrays;import java.util.Iterator;import java.util.List; public class FileIterator implements Iterator<File>, Iterabl

  • Java递归 遍历目录的小例子

    复制代码 代码如下: public static void main(String[] args) { File f = new File("D:\\test\\fsd");         listChids(f,0); } public static void listChids(File f,int level){ String preSrt = "";         for(int i=0;i<level;i++){ preSrt += "

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

    列出目录中的文件 用File类的list()方法可以很容易的列出目录中的所有文件的文件名.如果想要获取文件而不止是文件名的话,可以使用它的listFiles()方法.这很简单,难的是怎么去处理这个返回的列表.我们不再使用传统的冗长的外部迭代器,而是使用优雅的函数式来实遍历这个列表.这里我们还得用到JDK的新的CloseableStream接口以及一些相关的高阶函数. 下面这段代码可以列出当前目录下所有文件的名字. 复制代码 代码如下: Files.list(Paths.get(".")

  • Java 函数式编程要点总结

    目录 一.函数式概念 二.函数与方法 三.JDK函数基础 1.Lambda表达式 2.函数式接口 四.Optional类 1.Null判断 2.Optional应用 五.Stream流 六.源代码地址 一.函数式概念 函数式编程是一种结构化编程的范式,主要思想是把运算过程尽量写成系列嵌套的函数调用.函数编程的概念表述带有很抽象的感觉,可以基于案例看: public class Function01 {     public static void main(String[] args) {   

  • Java 函数式编程梳理

    目录 一.Lambda表达式 1.1 函数式编程思想概述 1.2 体验Lambda表达式 1.3 Lambda表达式的标准格式 1.4 Lambda表达式的练习 1.5 Lambda表达式的省略模式 1.6 Lambda表达式的注意事项 1.7 Lambda表达式和匿名内部类的区别 二.接口组成更新 1.1 接口组成更新概述 1.2 接口中默认方法 1.3 接口中静态方法 1.4 接口中私有方法 三.方法引用 1.1 体验方法引用 1.2 方法引用符 1.3 Lambda表达式支持的方法引用 1

  • 详解JAVA 函数式编程

    1.函数式接口 1.1概念: java中有且只有一个抽象方法的接口. 1.2格式: 修饰符 interface 接口名称 { public abstract 返回值类型 方法名称(可选参数信息); // 其他非抽象方法内容 } //或者 public interface MyFunctionalInterface { void myMethod(); } 1.3@FunctionalInterface注解: 与 @Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解

  • 详解Java函数式编程和lambda表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于某种语法或调用API去进行编程.例如,我们现在需要从一组数字中,找出最小的那个数字,若使用用命令式编程实现这个需求的话,那么所编写的代码如下: public static void main(String[] args) { int[] nums = new int[]{1, 2, 3, 4, 5,

  • Java函数式编程(八):字符串及方法引用

    第三章 字符串,比较器和过滤器 JDK引入的一些方法对写出函数式风格的代码很有帮助.JDK库里的一些的类和接口我们已经用得非常熟悉了,比如说String,为了摆脱以前习惯的那种老的风格,我们得主动寻找机会来使用这些新的方法.同样,当我们需要用到只有一个方法的匿名内部类时,我们现在可以用lambda表达式来替换它了,不用再像原来那样写的那么繁琐了. 本章我们会使用lambda表达式和方法引用来遍历字符串,实现Comparator接口,查看目录中的文件,监视文件及目录的变更.上一章中介绍的一些方法还

  • Java函数式编程(一):你好,Lambda表达式

    第一章 你好,lambda表达式! 第一节 Java的编码风格正面临着翻天覆地的变化. 我们每天的工作将会变成更简单方便,更富表现力.Java这种新的编程方式早在数十年前就已经出现在别的编程语言里面了.这些新特性引入Java后,我们可以写出更简洁,优雅,表达性更强,错误更少的代码.我们可以用更少的代码来实现各种策略和设计模式. 在本书中我们将通过日常编程中的一些例子来探索函数式风格的编程.在使用这种全新的优雅的方式进行设计编码之前,我们先来看下它到底好在哪里. 改变了你的思考方式 命令式风格--

  • Java函数式编程(三):列表的转化

    列表的转化 将集合转化成一个新的集合就和遍历它一样简单.假设我们要将列表中的名字转化成全大写的.我们看下都有哪些实现方式. Java中的字符串是不可变的,所以它没法改变.我们可以生成新的字符串,用来替换列表中原有的元素.然而这样做的话,原来列表就没了;还有一个问题,原来的列表可能也是不可变的,比如Arrays.asList()生成的,所以修改原来的列表这招不行.还有一个缺点就是这样做很难并行操作. 生成一个新的全大写的列表是个不错的选择. 乍听起来这个建议弱爆了;性能是我们都很关注的一个问题.令

  • Java函数式编程(七):MapReduce

    译注:map(映射)和reduce(归约,化简)是数学上两个很基础的概念,它们很早就出现在各类的函数编程语言里了,直到2003年Google将其发扬光大,运用到分布式系统中进行并行计算后,这个组合的名字才开始在计算机界大放异彩(那些函数式粉可能并不这么认为).本文我们会看到Java 8在摇身一变支持函数式编程后,map和reduce组合的首次亮相(这里只是初步介绍,后续还会有针对它们的专题). 对集合进行归约 现在为止我们已经介绍了几个操作集合的新技巧了:查找匹配元素,查找单个元素,集合转化.这

  • Java函数式编程(二):集合的使用

    第二章:集合的使用 我们经常会用到各种集合,数字的,字符串的还有对象的.它们无处不在,哪怕操作集合的代码要能稍微优化一点,都能让代码清晰很多.在这章中,我们探索下如何使用lambda表达式来操作集合.我们用它来遍历集合,把集合转化成新的集合,从集合中删除元素,把集合进行合并. 遍历列表 遍历列表是最基本的一个集合操作,这么多年来,它的操作也发生了一些变化.我们使用一个遍历名字的小例子,从最古老的版本介绍到现在最优雅的版本. 用下面的代码我们很容易创建一个不可变的名字的列表: 复制代码 代码如下:

随机推荐