Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 8 lambda expression for FilenameFilter

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

like image 410
SarthAk Avatar asked Mar 28 '15 10:03

SarthAk


People also ask

What is FilenameFilter in Java?

public interface FilenameFilter. java.io.FilenameFilter. Instances of classes that implement this interface are used to filter filenames. These instances are used to filter directory listings in the list method of class File , and by the Abstract Window Toolkit's file dialog component.

What is the lambda expression in Java 8?

Lambda Expressions were added in Java 8. A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

Is lambda expressions introduced in Java 8?

Introduction. Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection .

Can lambda expressions be used for all interfaces?

From Java 8 onwards, lambda expressions can be used to represent the instance of a functional interface. A functional interface can have any number of default methods.


Video Answer


2 Answers

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...

like image 123
Boris the Spider Avatar answered Oct 11 '22 04:10

Boris the Spider


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.

like image 21
T.Gounelle Avatar answered Oct 11 '22 04:10

T.Gounelle