free your lambdas

51
@ JosePaumard # FreeLambdas Free your Lambdas Java SE 8

Upload: jose-paumard

Post on 16-Apr-2017

683 views

Category:

Education


0 download

TRANSCRIPT

@JosePaumard#FreeLambdas

Free your Lambdas

Java SE 8

@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

@JosePaumard#FreeLambdas

Agenda

Other sessions:

TUT6198: Henri Tremblay, Mon 19 8h30-10h30

TUT 4041: Maurice Naftalin, Tue 20 8h30-10h30

CON5544: Collectors Fair, Tue 20 11h-12h Cont B 1/2/3

HOL3288: Lab on lambdas Wed 21 10h-12h

@JosePaumard

start

@JosePaumard#FreeLambdas

Questions?

#FreeLambdas

@JosePaumard#FreeLambdas

A first example

What is this code doing?

Comparator<Person> cmp = new Comparator<Person>() {

@Overridepublic int compare(Person p1, Person p2) {

return p1.getLastName().compareTo(p2.getLastName());}

};

@JosePaumard#FreeLambdas

A first example

What is this code doing?

Comparator<Person> cmp = new Comparator<Person>() {

@Overridepublic 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;}

}};

@JosePaumard#FreeLambdas

A first example

What is this code doing?Comparator<Person> cmp = new Comparator<Person>() {

@Overridepublic 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;

}}

};

@JosePaumard#FreeLambdas

A first example

What is this code doing?Comparator<Person> cmp = new Comparator<Person>() {

@Overridepublic 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;

}}

};

@JosePaumard#FreeLambdas

A first example

What is this code doing?

Comparator<Person> cmp = Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName).thenComparing(Person::getAge);

@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());}

};

@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) ;

@JosePaumard#FreeLambdas

A closer look at the Comparator

What did we do?

@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

@JosePaumard#FreeLambdas

A closer look at the Comparator

Why did we use an instance of an anoymous class?

@JosePaumard#FreeLambdas

A closer look at the Comparator

Why did we use an instance of an anoymous class?

Because there is no other way in Java 7!

@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()) ;

}

}

@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()) ;

@JosePaumard#FreeLambdas

Back to the Comparator interface

The Comparator interface…

public interface Comparator<T> {

public int compare(T t1, T t2) ;}

@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) ;}

@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) ;}

@JosePaumard#FreeLambdas

Back to the Comparator interface

A functional interface can be annotated

But it is optional

@FunctionalInterfacepublic interface Comparator<T> {

public int compare(T t1, T t2) ;}

@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

@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)

) ;

@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)

) ;

@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);

}

}

}

@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

@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!

@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

@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)

@JosePaumard#FreeLambdas

Package java.util.function

4 categories of functional interfaces:

ConsumerSupplierFunctionPredicate

@JosePaumard#FreeLambdas

Package java.util.function

4 categories of functional interfaces:

Consumer t -> {};Supplier () -> t;Function t -> u;Predicate t -> true;

@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;

@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;

@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;

@JosePaumard#FreeLambdas

Back to the Comparator

Let us write a comparator of people

- Using an anonymous class

- Then a lambda

@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

@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

@JosePaumard#FreeLambdas

What about patterns?

Let us talk about the GoF

@JosePaumard#FreeLambdas

What about patterns?

Let us talk about the GoF

The factory pattern

@JosePaumard#FreeLambdas

What about patterns?

Let us talk about the GoF

The factory pattern

The registry & builder patterns

@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

@JosePaumard#FreeLambdas

Thank you!

No snails were harmed during the preparation of this talk

@JosePaumard#FreeLambdas