The slides of my JavaOne 2016 talk. This talk is a tutorial on how to write lambda expressions, how to compose them using default methods in functional interfaces, and how to create factory methods in those interfaces. Many examples and patterns are provided.
2. @JosePaumard#FreeLambdas
Agenda
Tutorial session: we will start at the very beginning!
…and explore how to build functional interfaces to design
new APIs
This is about lambdas and functional interfaces
So not much about Streams & Collectors
8. @JosePaumard#FreeLambdas
A first example
What is this code doing?
Comparator<Person> cmp = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
return p1.getLastName().compareTo(p2.getLastName());
}
};
9. @JosePaumard#FreeLambdas
A first example
What is this code doing?
Comparator<Person> cmp = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int cmp = p1.getLastName().compareTo(p2.getLastName());
if (cmp == 0) {
return p1.getFirstName().compareTo(p2.getFirstName());
} else {
return cmp;
}
}
};
10. @JosePaumard#FreeLambdas
A first example
What is this code doing?
Comparator<Person> cmp = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int cmp = p1.getLastName().compareTo(p2.getLastName());
if (cmp == 0) {
cmp = p1.getLastName().compareTo(p2.getFirstName());
if (cmp == 0) {
return p1.getAge() - p2.getAge();
} else {
return cmp;
}
} else {
return cmp;
}
}
};
11. @JosePaumard#FreeLambdas
A first example
What is this code doing?
Comparator<Person> cmp = new Comparator<Person>() {
@Override
public int compare(Person p1, Person p2) {
int cmp = p1.getLastName().compareTo(p2.getLastName());
if (cmp == 0) {
cmp = p1.getFirstName().compareTo(p2.getFirstName());
if (cmp == 0) {
return p1.getAge() - p2.getAge();
} else {
return cmp;
}
} else {
return cmp;
}
}
};
12. @JosePaumard#FreeLambdas
A first example
What is this code doing?
Comparator<Person> cmp = Comparator.comparing(Person::getLastName)
.thenComparing(Person::getFirstName)
.thenComparing(Person::getAge);
13. @JosePaumard#FreeLambdas
A closer look at the Comparator
Suppose we want to sort strings of characters
1) We create a comparator:
Comparator<String> comparator = new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
};
14. @JosePaumard#FreeLambdas
A closer look at the Comparator
Suppose we want to sort strings of characters
1) We create a comparator:
2) We pass it to the right method:
Comparator<String> comparator = new Comparator<String>() {
public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
};
Arrays.sort(strings, comparator); Collections.sort(list, comparator) ;
16. @JosePaumard#FreeLambdas
A closer look at the Comparator
What did we do?
We passed a piece of code as a parameter to a method
And this method will use this code later
19. @JosePaumard#FreeLambdas
Another way of writing it
Our comparator:
Comparator<String> comparator = new Comparator<String>() {
public int compareTo(String s1, String s2) {
return Integer.compare(s1.length(), s2.length()) ;
}
}
20. @JosePaumard#FreeLambdas
Another way of writing it
Our comparator:
Becomes:
Comparator<String> comparator = new Comparator<String>() {
public int compareTo(String s1, String s2) {
return Integer.compare(s1.length(), s2.length()) ;
}
}
Comparator<String> comparator =
(String s1, String s2) ->
Integer.compare(s1.length(), s2.length()) ;
21. @JosePaumard#FreeLambdas
Back to the Comparator interface
The Comparator interface…
public interface Comparator<T> {
public int compare(T t1, T t2) ;
}
22. @JosePaumard#FreeLambdas
Back to the Comparator interface
The Comparator interface…
becomes a functional interface in Java 8
public interface Comparator<T> {
public int compare(T t1, T t2) ;
}
23. @JosePaumard#FreeLambdas
Back to the Comparator interface
The Comparator interface…
becomes a functional interface in Java 8
because it has a single abstract method
public interface Comparator<T> {
public int compare(T t1, T t2) ;
}
24. @JosePaumard#FreeLambdas
Back to the Comparator interface
A functional interface can be annotated
But it is optional
@FunctionalInterface
public interface Comparator<T> {
public int compare(T t1, T t2) ;
}
25.
26. @JosePaumard#FreeLambdas
So…
Writing a lambda is a matter of finding what interface to
implement
The type of a lambda is always known at compile time
The method is always the same:
- copy / paste the block of parameters
- little ASCII art arrow
- implement the method
27. @JosePaumard#FreeLambdas
A weird thing…
We wrote this code:
The forEach() method is defined on the Iterable interface
List<String> strings = ...;
strings.forEach(
System.out::println // method reference (bound instance)
) ;
28. @JosePaumard#FreeLambdas
A weird thing…
We wrote this code:
The forEach() method is defined on the Iterable interface
Do we really want to refactor all the Collection API?
List<String> strings = ...;
strings.forEach(
System.out::println // method reference (bound instance)
) ;
29. @JosePaumard#FreeLambdas
Default methods
Breaking the backward compatibility is not possible in Java
The way interfaces work has been modified:
public interface Iterable<E> {
// usual methods
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
30. @JosePaumard#FreeLambdas
Default methods
We can now add methods in interfaces with their
implementation
Those are « normal » methods
It is a new concept of interface, not a new concept of
method
31. @JosePaumard#FreeLambdas
Default & static methods
We can now add methods in interfaces with their
implementation
Those are « normal » methods
It is a new concept of interface, not a new concept of
method
And static methods are allowed too!
32. @JosePaumard#FreeLambdas
Back to the functional interface
A functional interface is an interface
with only one abstract method
So default & static methods do not count
33.
34. @JosePaumard#FreeLambdas
So…
Interfaces in Java 8:
- Functional interfaces to write lambda expressions
- Default methods, can be used to compose them
- Static methods, can be used as factory
We better readability, better robustness…
and better performances!
(Youtube: Lambda a peek under the hood by B. Goetz)
37. @JosePaumard#FreeLambdas
Package java.util.function
4 categories of functional interfaces:
Consumer t -> {}; s -> System.out.println(s);
Supplier () -> t; () -> new Ballon();
Function t -> u; person -> person.getAge();
Predicate t -> true; age -> age > 20;
38. @JosePaumard#FreeLambdas
Package java.util.function
4 categories of functional interfaces:
Runnable () -> {};
Consumer t -> {}; s -> System.out.println(s);
Supplier () -> t; () -> new Ballon();
Function t -> u; person -> person.getAge();
Predicate t -> true; age -> age > 20;
39. @JosePaumard#FreeLambdas
Package java.util.function
4 categories of functional interfaces:
Runnable () -> {}; () -> logger.log(message);
Consumer t -> {}; s -> System.out.println(s);
Supplier () -> t; () -> new Ballon();
Function t -> u; person -> person.getAge();
Predicate t -> true; age -> age > 20;
42. @JosePaumard#FreeLambdas
Method reference
There are 4 types of method references
Nom Syntaxe
Static RefType::staticMethod
Bound instance expr::instMethod
Unbound instance RefType::instMethod
Constructor ClassName::new
43. @JosePaumard#FreeLambdas
Method reference
There are 4 types of method references
Lambda Method Reference
d -> Math.sin(d) Math::sin
s -> System.out.println(s) System.out::println
(s, t) -> s.compareTo(t) String::compareTo
name -> new Person(name) Person::new
49. @JosePaumard#FreeLambdas
Conclusion
Lambdas are not just a nice way of writing instances of
anonymous classes
Functional interfaces + default methods + factory methods
provide new ways of implementing well-known patterns for
our applications & APIs