FilenameFilter的java 8 lambda表达式

我正在浏览java 8中的lambda表达式

当我改变线程代码时,它工作正常

new Thread(new Runnable() { @Override public void run() { System.out.println("run"); } }).start(); 

转换为lambda表达式为

 new Thread( () -> System.out.println("Hello from thread") ).start(); 

但我无法转换FilenameFilter表达式

 File file = new File("/home/text/xyz.txt"); file.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { name.endsWith(".txt"); return false; } }); 

并且未成功转换为此

 file.list(new FilenameFilter () { (File a1, String a2) -> { return false; } }); 

它像日食一样给出错误

此行有多个标记
– 语法错误,插入“;” 完成声明
– 语法错误,插入“}”以完成阻止
– 语法错误,插入“AssignmentOperator Expression”以完成分配

首先,你的格式是可怕的 ,整理出来!

现在,lambda语法; 转换匿名类:

 final FilenameFilter filter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return false; } }; 

我们首先将单个方法accept(File dir, String name)的等效lambda替换为匿名类:

 final FilenameFilter filter = (File dir, String name) -> { return false; }; 

但我们可以做得更好,我们不需要定义类型 – 编译器可以解决这些问题:

 final FilenameFilter filter = (dir, name) -> { return false; }; 

而且我们可以做得更好,因为该方法返回一个boolean ; 如果我们有一个评估为boolean语句,我们可以跳过return和大括号:

 final FilenameFilter filter = (dir, name) -> false; 

这可以是任何语句,例如:

 final FilenameFilter filter = (dir, name) -> !dir.isDirectory() && name.toLowerCase().endsWith(".txt"); 

但是, File API 老,所以不要使用它。 使用nio API 。 自2011年Java 7以来,这已经存在,所以没有任何借口:

 final Path p = Paths.get("/", "home", "text", "xyz.txt"); final DirectoryStream.Filter f = path -> false; try (final DirectoryStream stream = Files.newDirectoryStream(p, f)) { stream.forEach(System.out::println); } 

实际上你的例子有一个特定的方法内置到带有Glob的 Files中:

 final Path p = Paths.get("/", "home", "text", "xyz.txt"); try (final DirectoryStream stream = Files.newDirectoryStream(p, "*.txt")) { stream.forEach(System.out::println); } 

或者,使用更现代的Files.list

 final Path p = Paths.get("/", "home", "text", "xyz.txt"); final PathMatcher filter = p.getFileSystem().getPathMatcher("glob:*.txt"); try (final Stream stream = Files.list(p)) { stream.filter(filter::matches) .forEach(System.out::println); } 

这里filter::matches是一个方法引用,因为PathMatcher.matches可用于实现function接口Predicate因为它接受一个Path并返回一个boolean


作为旁白:

 f.list(new FilenameFilter() { @Override public boolean accept(File dir, String name) { name.endsWith(".txt"); return false; } }); 

这毫无意义……

它应该更简单:

 f.list((File a1, String a2) -> {return false;}); 

甚至 :

 f.list((a1,a2) -> {return false;}); 

lambda表达式替换抽象类实例的实例化。

FileNameFilter是一个function接口。 您不需要显式实例化它。

  f.list((dir, name) -> name.endsWith(".txt")); 

另请注意, f应该是目录,而不是示例中的文件。 f1是文件的示例将使用指定的filter返回null

如果使用lambda表达式,则不必放置类名:

  f.list( (File a1, String a2) -> { return false; } ); 

实际上,在第一个示例中,省略了new Runnable()