问题
I am going through the lambda expression in java 8
when i changed the code of thread it's working fine
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("run");
}
}).start();
is converted to lambda expression as
new Thread(
() -> System.out.println("Hello from thread")
).start();
But i am not able to convert the 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;
}
});
and unsuccessfully converted to this as
file.list(new FilenameFilter () {
(File a1, String a2) -> {
return false;
}
});
it's giving error as in eclipse as
Multiple markers at this line
- Syntax error, insert ";" to complete Statement
- Syntax error, insert "}" to complete Block
- Syntax error, insert "AssignmentOperator Expression" to complete Assignment
回答1:
First things first, your formatting is horrible, sort it out!
Now, lambda syntax; to convert the anonymous class:
final FilenameFilter filter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return false;
}
};
We start by replacing the anonymous class with an equivalent lambda for the single method accept(File dir, String name):
final FilenameFilter filter = (File dir, String name) -> {
return false;
};
But we can do better, we don't need to define the types - the compiler can work those out:
final FilenameFilter filter = (dir, name) -> {
return false;
};
And we can do better still, as the method return a boolean; if we have a single statement that evaluates to a boolean we can skip the return and the braces:
final FilenameFilter filter = (dir, name) -> false;
This can be any statement, for example:
final FilenameFilter filter = (dir, name) -> !dir.isDirectory() && name.toLowerCase().endsWith(".txt");
However, the File API is very old, so don't use it. Use the nio API. This has been around since Java 7 in 2011 so there is really no excuse:
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);
}
And in fact your example has a specific method built into Files that 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);
}
Or, using the more modern 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);
}
Here filter::matches is a method reference because the method PathMatcher.matches can be used to implement the functional interface Predicate<Path> as it takes a Path and returns a boolean.
As an aside:
f.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
name.endsWith(".txt");
return false;
}
});
This makes no sense...
回答2:
It should be simpler :
f.list((File a1, String a2) -> {return false;});
or even :
f.list((a1,a2) -> {return false;});
The lambda expression replaces the instantiation of the abstract class instance.
回答3:
FileNameFilter is a functional interface. You don't need to instantiate it explicitly.
f.list((dir, name) -> name.endsWith(".txt"));
Note also, that f should be a directory, not a file as in your example. Your example where f1 is a file will return null with the specified filter.
回答4:
You don't have to put the class name, if you use a lambda-expression:
f.list(
(File a1, String a2) -> {
return false; }
);
In fact, in your first example, you omit new Runnable().
来源:https://stackoverflow.com/questions/29316310/java-8-lambda-expression-for-filenamefilter