【问题标题】:java 8 lambda expression for FilenameFilterFilenameFilter 的 java 8 lambda 表达式
【发布时间】:2015-06-01 16:53:09
【问题描述】:

我正在通过 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;
    }
});

它在eclipse中给出错误

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

【问题讨论】:

  • 如果您使用 Java 8,为什么要使用 File?为什么不是 java.nio.file?
  • 您应该接受一个答案,以确认问题已解决...
  • 感谢@lodo 的回答
  • @fge 我从现在开始使用它
  • 由于这在 Google 上出现了很多,这里是 Java 8 中的一个单行:Files.list(Paths.get("your/path")).filter(path -> path.toString().endsWith(".txt")).collect(Collectors.toList());

标签: java lambda java-8


【解决方案1】:

首先,您的格式糟糕,请解决!

现在,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&lt;Path&gt;,因为它接受Path并返回一个boolean


顺便说一句:

f.list(new FilenameFilter() {

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

这毫无意义……

【讨论】:

  • 有什么理由不使用 File API 只是因为它太旧了吗?
  • @citizenconn 首先是; File API 有糟糕的错误报告,大多数方法返回一个boolean,让您自己来解决操作失败的原因。其他问题是缺乏功能,NIO API 有大量的实用功能,几乎可以用于任何事情。最后,实际上使用旧 API 从文件 读取 是冗长且容易出错的 - NIO 极大地简化了整个过程,例如默认字符集是 UTF-8,而不是您当前平台决定的任何字符集。这只是初学者......
  • nio API 在 Android 7 操作系统中不工作,我收到错误
【解决方案2】:

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

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

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

【讨论】:

  • 当我找到“用于 FilenameFilter 的 java 8 lambda 表达式”页面时,正是我正在寻找的单行解决方案。谢谢。
【解决方案3】:

应该更简单:

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

甚至:

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

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

【讨论】:

  • 甚至(file, n) -&gt; false。没有理由使用块。
【解决方案4】:

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

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

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

【讨论】:

  • 这种格式同样可怕,答案几乎错了。
猜你喜欢
  • 2017-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多