Java 8 lambda expression for FilenameFilter

I am looking at lambda expression in java 8

when i changed the stream code that works fine

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

converts to lambda expression as

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

But I can not convert the expression 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; } }); 

and unsuccessfully converted to this as

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

it gives an error like in eclipse like

Several markers on this line
- Syntax error, insert ";" Complete Statement
- Syntax error, insert "}" to complete the block
- Syntax error, insert the expression "AssignmentOperator Expression" to complete the job

+7
java lambda java-8
source share
4 answers

First of all, your formatting is awful , sort it!

Now the lambda syntax; to convert an anonymous class:

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

Let's start by replacing the anonymous class with the equivalent lambda for the only accept(File dir, String name) method:

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

But we can do better, we do not need to define types - the compiler can process them:

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

And we can do even better, since the method returns a boolean ; if we have one statement that evaluates to boolean , we can skip return and braces:

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

It 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 do not use it. Use the nio API . This has been around since Java 7 in 2011, so there really is no :

 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 actually your example has a special method built into Files that accepts 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 reference to a method, because the PathMatcher.matches method can be used to implement the Predicate<Path> functional interface, since it takes Path and returns a boolean .


Aside:

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

It does not make sense...

+31
source share

It should be simpler:

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

or even:

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

A lambda expression replaces an instance of an abstract class instance.

+5
source share

You do not need to specify a class name if you use a lambda expression:

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

In fact, in the first example, you omit new Runnable() .

+2
source share

FileNameFilter is a functional interface. You do not need to explicitly specify it.

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

Note that f must be a directory, not a file, as in your example. Your example, where f1 is a file, returns null with the specified filter.

+2
source share

All Articles