当前位置:  编程技术>java/j2ee

Java函数式编程(十二):监控文件修改

    来源: 互联网  发布时间:2014-11-08

    本文导语:  使用flatMap列出子目录 前面已经看到如何列出指定目录下的文件了。我们再来看下如何遍历指定目录的直接子目录(深度为1),先实现一个简单的版本,然后再用更方便的flatMap()方法来实现。 我们先用传统的for循环来遍历一个...

使用flatMap列出子目录

前面已经看到如何列出指定目录下的文件了。我们再来看下如何遍历指定目录的直接子目录(深度为1),先实现一个简单的版本,然后再用更方便的flatMap()方法来实现。

我们先用传统的for循环来遍历一个指定的目录。如果子目录中有文件,就添加到列表里;否则就把子目录添加到列表里。最后,打印出所有文件的总数。代码在下面——这个是困难模式的。

代码如下:

public static void listTheHardWay() {
     List<File> files = new ArrayList<>();
     File[] filesInCurrentDir = new File(".").listFiles();
     for(File file : filesInCurrentDir) {
          File[] filesInSubDir = file.listFiles();
               if(filesInSubDir != null) {
                     files.addAll(Arrays.asList(filesInSubDir));
               } else {
                    files.add(file);
               }
      }
     System.out.println("Count: " + files.size())
}

我们先获取当前目录下的文件列表,然后进行遍历。对于每个文件,如果它有子文件,就把它们添加到列表中。这样做是没问题的,不过它有一些常见的问题:可变性,基本类型偏执,命令式,代码冗长,等等。一个叫flatMap()的小方法就可以解决掉这些问题。

正如这个名字所说的,这个方法在映射后会进行扁平化。它会像map()一样对集合中的元素进行映射。但是和map()方法不同的是,map()方法里面的lambda表达式只是返回一个元素,而这里返回的是一个Stream对象。于是这个方法将多个流压平,将里面的每个元素映射到一个扁平化的流中。

我们可以用flatMap()来执行各种操作,不过现在手头的这个问题就正好诠释了它的价值。每个子目录都有一个文件的列表或者说流,而我们希望获取当前目录下的所有子目录中的文件列表。

有一些目录可能是空的,或者说没有子元素。这种情况下,我们将这个空目录或者文件包装成一个流对象。如果我们想忽略某个文件,JDK中的flatMap()方法也可以很好的处理空文件;它会把一个空引用作为一个空集合合并到流里。来看下flatMap()方法的使用。

代码如下:

public static void betterWay() {
     List<File> files =
          Stream.of(new File(".").listFiles())
               .flatMap(file -> file.listFiles() == null ?
                    Stream.of(file) : Stream.of(file.listFiles()))
               .collect(toList());
     System.out.println("Count: " + files.size());
}

我们先是获取了当前目录的子文件流,然后调用了它的flatMap()方法。然后将一个lambda表达式传给这个方法,这个表达式会返回指定文件的子文件的流。flatMap()方法返回的的是当前目录所有子目录下的文件的集合。我们使用collect()方法以及Collectors里面的toList()(方法把它们收集到一个列表中。

我们传给flatMap()的这个lambda表达式,它返回的是一个文件的子文件。 如果没有的话,则返回这个文件的流。flatMap()方法优雅地将这个流映射到一个流的集合中,然后将这个集合扁平化,最终合并到一个流中。

flatMap()方法减少了许多开发的工作——它将两个连续的操作很好的结合到了一起,这通常称为元组 ——用一个优雅的操作就完成了。

我们已经知道如何使用flatMap()方法来将直接子目录中的所有文件列出来。下面我们来监控一下文件的修改操作。

监控文件修改

我们已经知道如何查找文件及目录,不过如果我们希望在文件创建,修改或删除的时候,能够接收到提示消息的话,这个也非常简单。这样的机制对于监视一些特殊文件比如配置文件,系统资源的改动非常有用。下面我们来探索下Java 7中引入的这个工具,WatchService,它可以用来监控文件的修改。下面我们看到的许多特性都来自JDK 7,而这里最大的改进就是内部迭代器带来的便利性。

我们先来写个监控当前目录中的文件修改的例子。JDK中的Path类会对应文件系统中的一个实例,它是一个观察者服务的工厂。我们可以给这个服务注册通知事件,就像这样:

代码如下:

inal Path path = Paths.get(".");

final WatchService watchService =
       path.getFileSystem()
           .newWatchService();
       path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);

System.out.println("Report any file changed within next 1 minute...");

我们注册了一个WatchService来观察当前目录的修改。你可以轮询这个WatchService来获取目录下文件的修改操作,它会通过一个WatchKey将这些改动返回给我们。一旦我们拿到了这个key,可以遍历它的所有事件来获取文件更新的详细信息。因为可能会有多个文件被同时修改,poll操作可能会返回多个事件。来看下轮询以及遍历的代码。

代码如下:

final WatchKey watchKey = watchService.poll(1, TimeUnit.MINUTES);

if(watchKey != null) {
     watchKey.pollEvents()
          .stream()
          .forEach(event ->
               System.out.println(event.context()));
}

这里可以看到,Java 7和Java 8的特性同时出场了。我们把pollEvents()返回的集合转化成了一个Java 8的Stream,然后使用它的内部迭代器来打印出每个文件的详细的更新信息。

我们来运行下这段代码,然后将当前目录下的sample.txt文件修改一下,看下这个程序是否能察觉这个更新。

代码如下:

Report any file changed within next 1 minute...

sample.txt

当我们修改了这个文件的时候,程序会提示说文件被修改了。我们可以用这个功能来监视不同文件的更新,然后执行相应的任务。当然我们也可以只注册文件新建或者删除的操作。

总结

有了lambda表达式和方法引用后,像字符串及文件的操作,创建自定义比较器这些常见的任务都变得更简单也更简洁了。匿名内部类也变得优雅起来了,而可变性就像日出后的晨雾一样,也消失得无影无踪了。使用这种新风格进行编码还有一个福利,就是你可以使用JDK的新设施来高效地遍历庞大的目录。

现在你已经知道如何创建lambda表达式并把它传递给方法了。下一章我们会介绍如何使用函数式接口及lambda表达式进行软件的设计。


    
 
 

您可能感兴趣的文章:

  • java的数学函数在那个类中,如幂函数、指数、对数、双曲线函数等?
  • 怎样用JAVA函数读写注册表,有这样的函数吗
  • java 的条件判断函数(类似于别的语言iif函数)
  • linux下C++ 通过JNI回调java函数,回调函数时间过长
  • PHP中的Pack()函数,Java有哪个函数与之对应???
  • JAVA中函数调用时,能不能向 C/C++一样函数的入口参数可以为传出值(就是引用,或指针)
  • 急!请问有分析java程序性能瓶颈的工具吗?例如,统计 java 程序中函数调用次数?
  • java里有什么函数可以检查 java 代码并执行它?
  • 请问在JAVA里将小写字母换为大写字母是用什么函数,大写转成小写又是用哪个函数?
  • 谁能告诉我,在JAVA中,哪个函数和ASP中的Int()函数等同,也就是取整函数
  • java类中的方法就是函数了,函数参数全是传值了,传址参数怎样表示?
  • 虚函数与纯虚函数(C++与Java虚函数的区别)的深入分析
  • Java中有不有与VB中Replace函数功能类似的函数?
  • java中函数的缺省参数怎么定义?
  • 如何实现Java下的回调函数!
  • 有关Java构造函数的问题之一——缺省性
  • 关于java函数?
  • ▲ JAVA函数大全!!! ▲
  • ******关于java中调用函数的问题********
  • 谁有java函数大全,100重酬!!
  • Java程序监控API Java Simon
  • java语言实现监控程序
  • Java监控和分析 Memory Analyzer
  • Java文件监控库 jpathwatch
  • Linux文件系统监控的Java类库 inotify-java
  • Java 虚拟机监控工具 WebMon
  • Java 监控解决方案 Apache Sirona
  • 在linux里面怎么监控一个java程序的运行? 急
  • Java 应用性能监控工具 Illuminate
  • 中央式监控工具 Java-monitor
  • 开发的java工程系统运行在linex上,现在想监控这个系统的运行情况
  •  
    本站(WWW.169IT.COM)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.169IT.COM)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 在线等待:在Java中是否有权限修改一个文件的权限?
  • Solaris下如何修改java虚拟机的默认编码
  • Java难题,Java如何修改Windows注册表?
  • java可以修改http头么
  • 如何修改tomcat.sh文件,限定java使用的内存?????
  • java的应用程序中如何定义一个全局变量,在程序的任何地方都可以修改使用?
  • 用java程序修改unix下用户的口令
  • Java批量修改文件名的实例代码
  • linux /etc/profile/ 修改后不能登录系统 java环境变量设置 无法保存
  • 有关结果数据集的修改-java和ORACLE数据库
  • 初等问题:我刚安装上Java,却找不到Javac,按说明我去修改autoexec.bat,但是,我的autoexec.bat文件是空的.请问autoexec.bat文件的标准格式
  • 谁告诉我如何使用java创建,分析,修改一个xml,给我例子
  • Java的跨平台是不是说用Java写的程序代码不需要修改就可以在各种操作系统平台下运行?它与C++/C的跨平台有什么不同之处?
  • 新学JAVA做了个 QQ ,请大侠测试,给出建议或buf或修改意见的给源码,--UP有分
  • java怎么创建目录(删除/修改/复制目录及文件)代码实例
  • 请问如何修改java中的默认字体等等!
  • java命名空间java.sql类types的类成员方法: java_object定义及介绍
  • 我想学JAVA ,是买THINK IN JAVA 还是JAVA2核心技术:卷1 好???
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: imageflavor定义及介绍
  • 请问Java高手,Java的优势在那里??,Java主要适合于开发哪类应用程序
  • java命名空间java.lang.management类managementfactory的类成员方法: getcompilationmxbean定义及介绍
  • 如何将java.util.Date转化为java.sql.Date?数据库中Date类型对应于java的哪个Date呢
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getlibrarypath定义及介绍
  • 谁有电子版的《Java编程思想第二版(Thinking in java second)》和《Java2编程详解(special edition java2)》?得到给分
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getstarttime定义及介绍
  • 本人想学java,请问java程序员的待遇如何,和java主要有几个比较强的方向
  • java命名空间java.awt.datatransfer类dataflavor的类成员方法: stringflavor定义及介绍
  • 我对JAVA一窍不通,可惜别人却给我一个Java的project,要我做一个安装程序,请问哪里有JAVA INSTALLER下载,而且我要不要安装java的sdk才能完成此项任务?
  • java命名空间java.security类keystore的类成员方法: getdefaulttype定义及介绍
  • 新年第一天,让我们讨论一下未来一年JAVA的发展趋势! 个人认为,JAVA将主要朝ERP和JAVA手机方面发展!
  • java命名空间java.lang.management接口runtimemxbean的类成员方法: getclasspath定义及介绍


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2017,169IT.COM,E-mail:www_169it_com#163.com(请将#改为@)

    浙ICP备11055608号