To talk about lambda functions and functional programming we must first talk about functional interfaces.
A functional interface is an interface with one and only one abstract method. They have a special relationship with lambda expressions.
From Java 8 we can find many functional interfaces in java.util.function
package.
A functional interface can also have static and default methods. For instance, java.util.function.Predicate
has five methods: and()
, isEqual()
, negate()
, or()
and only one abstract test()
method.
Methods inheritated from Object don’t count so Object.equals()
method doesn’t count, like other static and default methods. The only abstract method is callen functional method.
// Foo.java: a functional interface
interface Foo {
public void foof();
}
...
// An anonymous inner class
Bar b = new Bar();
b.doStuff(new Foo() {
public void foof() {
System.out.println("foofy");
}
});
...
...
// An anonymous inner class
Bar b = new Bar();
b.doStuff(() -> System.out.println("foofy"));
...
A famous example of a functional interface is Comparator with its sort()
method. In our example DVDInfo
is a class of informations about film DVDs and we have to sort by genre a List
of DVDInfo
s.
We can use the classic implementation of Comparator<T>
:
class GenreSort implements Comparator<DVDInfo> {
public int compare(DVDInfo dvd1, DVDInfo dvd2) {
return dvd1.getGenre().compareTo(dvd2.getGenre());
}
}
We can set it like an anonymous inner class:
Comparator<DVDInfo> genreSort = new Comparator<DVDInfo>() {
public int compare(DVDInfo dvd1, DVDInfo dvd2) {
return dvd1.getGenre().compareTo(dvd2.getGenre());
}
};
dvdlist.sort(genreSort); // used to sort our list
And from Java 8 we can also use lambda:
dvdlist.sort((dvd1, dvd2) -> dvd.getGenre().compareTo(dvd2.getGenre()));
We can also pass the lambda inside a Comparator<DVDInfo>
variable.
Which is your favorite implementation?
Lambda expressions for functional interfaces
Lambda functions are a compact way to use a functional interface. We can transform functional interfaces into lambda expressions.
We can omit something if we have only one argument without type or only a statement.
If we have only one expression we can not use curly braces. Lambda will know that this is a void method and for expressions with return it threats it like returned.
These are all equivalent expressions:
DogQuerier dq = d -> d.getAget() > 9;
DogQuerier dq = (d) -> d.getAget() > 9;
DogQuerier dq = (Dog d) -> d.getAget() > 9;
DogQuerier dq = d -> { return d.getAget() > 9 };
With arg type (Dog in our example above) or with more than one argument w must add parenthesis. If we use return we must add curly braces or also for more than one statement.
A lambda can get variables from its outside enclosing scope but it cannot modify them.
Varibles from outside have to be final or effectively final (whose value isn’t changed after it is initialized).
int numCats = 3;
int numDogs = 1;
DogQuerier dq = d -> {
int numDogs = 5; // not compiles!
numCats++; // not compiles!
System.out.println(numCats); // OK, only accessing
System.out.println(numDogs); // OK, only accessing
};
If we declare and modify a variable all in a lambda expression it’s ok.
Method References in lambda expressions
There is a shorthand (also called a “sugar syntax”) to write lambda expressions, called method reference.
class Refs {
public static void main(String[] args) {
List<String> trees = Arrays.asList("Elm", "Cypress", "Ash");
trees.forEach(t -> System.out.println(t)); // A classic lambda
trees.forEach(System.out::println); // Method reference
trees.forEach(Refs::print); // Refs is a our example class with its method
}
public static void print(String t) {
System.out.println(t);
}
}
There are also instance method references:
// A lambda:
p -> p.getName()
// Can become:
Potter::getName
I suggest you also read the following article, where we deepen the most used and generic functional interface categories:
That’s all with lambda expressions and functional interfaces.
Try it at home!
Asking questions are really fastidious thing if you are not understanding something fully, except this paragraph provides good understanding even. Lorie Johnny Dwan
Really appreciate you sharing this blog post. Really looking forward to read more. Fantastic. Stephenie Gustavo Kampmann