FilenameFilter的java 8 lambda表达式

时间:2015-03-28 10:57:10

标签: java lambda java-8

我正在浏览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 Expression

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

它在eclipse中给出错误

  

此行的多个标记
     - 语法错误,插入“;”完成声明
     - 语法错误,插入“}”以完成块
     - 语法错误,插入“AssignmentOperator Expression”以完成作业

4 个答案:

答案 0 :(得分:43)

首先,您的格式是可怕,将其整理出来!

现在,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<Path> f = path -> false;
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(p, f)) {
    stream.forEach(System.out::println);
}

事实上,您的示例在Files中内置了一个特定的方法takes a Glob

final Path p = Paths.get("/", "home", "text", "xyz.txt");
try (final DirectoryStream<Path> 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<Path> stream = Files.list(p)) {
    stream.filter(filter::matches)
          .forEach(System.out::println);
}

此处filter::matches是方法引用,因为方法PathMatcher.matches可用于实现功能接口Predicate<Path>,因为它需要Path并返回boolean }。


暂且不说:

f.list(new FilenameFilter() {

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

这没有任何意义......

答案 1 :(得分:6)

应该更简单:

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

甚至:

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

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

答案 2 :(得分:5)

FileNameFilter是一个功能界面。您无需显式实例化它。

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

另请注意,f应该是目录,而不是示例中的文件。您f1是文件的示例将返回带有指定过滤器的null

答案 3 :(得分:2)

如果使用lambda表达式,则不必输入类名:

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

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