java 8 - nuts and bold - sfeir benelux

126
Yohan Beschi JAVA Expert

Upload: yohanbeschi

Post on 16-Jul-2015

59 views

Category:

Technology


5 download

TRANSCRIPT

Yohan BeschiJAVA Expert

I II III

1

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

@Override

public int compare(Person o1, Person o2) {

return o1.firstname.compareTo(o2.firstname);

}

};

Comparator<Person> comparator =

(Person o1, Person o2)

-> o1.firstname.compareTo(o2.firstname);

Comparator<Person> comparator1 =

(o1, o2) -> o1.firstname.compareTo(o2.firstname);

Comparator<Person> comparator1 =

(o1, o2) -> {

return o1.firstname.compareTo(o2.firstname);

};

Comparator<Person> comparator1 =

(o1, o2) -> throw new Exception("Something went wrong");

Comparator<Person> comparator1 =

(o1, o2) -> throw new Exception("Something went wrong");

THE CONTENT OF THE LAMBDA MUST MATCH THE SIGNATURE OF THE METHOD IMPLEMENTED

Comparator<Person> comparator1 =

(o1, o2) -> throw new RuntimeException("Something went wrong");

RUNTIME EXCEPTION - THIS WILL COMPILE

2

@FunctionalInterface

public interface Compare<T> {

int compare(T o1, T o2);

boolean equals(Object obj);

}

public interface NotAFunctionalInterface {

int doSomething();

Object clone(); // Not public

}

public interface Function<T, R> {

R apply(T t);

}

Function<String, String> function = x -> x.toUpperCase();

Function<String, Function<String, String>> function

= x -> y -> y.toUpperCase();

public interface Supplier<T> {

T get();

}

Supplier<String> supplier = () -> "String1";

public interface Consumer<T> {

void accept(T t);

}

Consumer<String> consumer =

x -> System.out.println(x.toLowerCase());

public interface Predicate<T> {

boolean test(T t);

}

Predicate<Double> predicate = x -> x > 10.5;

public interface IntConsumer {

void accept(int value);

}

IntConsumer consumer = x -> System.out.println(x);

public interface BiFunction<T, U, R> {

R apply(T t, U u);

}

BiFunction<BigDecimal> function =

(left, right) -> left.multiply(right);

public interface BinaryOperator<T> extends BiFunction<T,T,T> {

// inherits: R apply(T t, U u);

}

BiFunction<BigDecimal> function =

(left, right) -> left.multiply(right);

3

public interface Postfixable {

public final static int UNARY_MESSAGE_PRIORITY = 1;

public final static int BINARY_MESSAGE_PRIORITY = 2;

// ...

int getPriority();

public default boolean le(Postfixable other) {

return this.getPriority() <= other.getPriority();

}

}

public interface Formula {

double calculate(int a);

default double sqrt(int a) {

return Math.sqrt(positive(a));

}

}

Formula formula = (a) -> sqrt( a * 100);

public interface Formula {

double calculate(int a);

default double sqrt(int a) {

return Math.sqrt(positive(a));

}

}

Formula formula = (a) -> sqrt( a * 100);

DOES NOT COMPILE

public static interface MyInterface1 {

default void foo(){

System.out.println("hello");

}

}

public static interface MyInterface2 {

default void foo(){

System.out.println("bye");

}

}

public static class MyClass implements MyInterface1, MyInterface2 {

// ...

}

public static class MyClass implements MyInterface1, MyInterface2 {

// ...

} DOES NOT COMPILE

public static abstract class MyClass

implements MyInterface1, MyInterface2 {

public abstract foo();

}

UN-IMPLEMENTING THE DEFAULT METHOD SOLVES THE PROBLEM

public static class MyClass implements MyInterface1, MyInterface2 {

public void foo() {

MyInterface1.super.foo();

MyInterface2.super.foo();

}

}

public static class MyClass1 implements MyInterface1 {

public void foo(){

System.out.println("bonjour");

}

}

public static class MyClass2 extends MyClass1 implements MyInterface2 {

}

public static class MyClass1 implements MyInterface1 {

public void foo(){

System.out.println("bonjour");

}

}

public static class MyClass2 extends MyClass1 implements MyInterface2 {

}

IN CASE OF AMBIGUITY A CLASS TAKES PRECEDENCE

4

public class Car {

public static Car create(final Supplier<Car> supplier) {

return supplier.get();

}

public static void collide(final Car car) {

System.out.println("Collided " + car.toString());

}

public void repair() {

System.out.println("Repaired " + this.toString());

}

public void follow(final Car another) {

System.out.println("Following the " + another.toString());

}

}

final Car car = Car.create(Car::new);

final List<Car> cars = Arrays.asList(car);

final Car car = Car.create(Car::new);

final List<Car> cars = Arrays.asList(car);

cars.forEach(Car::collide);

final Car car = Car.create(Car::new);

final List<Car> cars = Arrays.asList(car);

cars.forEach(Car::repair);

final Car car = Car.create(Car::new);

final List<Car> cars = Arrays.asList(car);

final Car police = Car.create(Car::new);

cars.forEach(police::follow);

public static UtfToCodePoint findUtfToCodePoint(final Charset charset) {

switch (charset) {

case UTF8:

case UTF8BOM:

return Converter::utf8ToCodePoint;

case UTF16BE:

return Converter::utf16beToCodePoint;

case UTF16LE:

return Converter::utf16leToCodePoint;

case UTF32BE:

return Converter::utf32beToCodePoint;

case UTF32LE:

return Converter::utf32leToCodePoint;

default:

throw new UnicodeException("Unknown charset!");

}

}

public class Person {

final private String firstName;

final private String lastName;

public Person() {}

public Person(String firstName, String lastName) {

this.firstName = firstName;

this.lastName = lastName;

}

}

public interface PersonFactory {

Person create(String firstName, String lastName);

}

PersonFactory<Person> personFactory = Person::new;

Person person = personFactory.create("Peter", "Parker");

5

Predicate<String> predicate = (s) -> s.length() > 0;

predicate.test("foo"); // true

predicate.negate().test("foo"); // false

Predicate<String> nonNull = Objects::nonNull;

Predicate<String> isNull = Objects::isNull;

Predicate<String> isEmpty = String::isEmpty;

Predicate<String> isNotEmpty = isEmpty.negate();

Function<String, Integer> toInteger = Integer::valueOf;

Function<String, String> backToString = toInteger.andThen(String::valueOf);

backToString.apply("123"); // "123"

Supplier<Person> personSupplier = Person::new;

personSupplier.get(); // new Person

Consumer<Person> greeter = p -> System.out.println("Hello, " + p.firstName);

greeter.accept(new Person("Luke", "Skywalker"));

6

Optional<String> optional = Optional.of("foo");

optional.isPresent(); // true

optional.get(); // "foo"

optional.orElse("fallback"); // "foo"

optional.ifPresent((s) -> System.out.println(s.charAt(0))); // "f"

Optional<String> fullName = Optional.ofNullable(null);

System.out.println("Full Name is set? " + fullName.isPresent());

// Full Name is set? false

System.out.println("Full Name: " + fullName.orElseGet(() -> "[none]"));

// Full Name: [none]

System.out.println(fullName.map(s -> "Hey " + s + "!").orElse("Hey Stranger!"));

// Hey Stranger!

Optional<String> firstName = Optional.of("Tom");

System.out.println("First Name is set? " + firstName.isPresent());

// Full Name is set? true

System.out.println("First Name: " + firstName.orElseGet(() -> "[none]"));

// Full Name: Tom

System.out.println(firstName.map(s -> "Hey " + s + "!").orElse("Hey Stranger!"));

// Hey Tom!

7

public class Collections {

public static <T> void copy(List<? super T> dest, List<? extends T> src) {

for (int i = 0; i < src.size(); i++)

dest.set(i,src.get(i));

}

}

List<A> as = new ArrayList<>();

List<B> bs = new ArrayList<>();

List<C> cs = new ArrayList<>();

Collections.copy(List<A>, List<B>);

Collections.copy(List<A>, List<A>);

Collections.copy(List<A>, List<C>);

Collections.copy(List<B>, List<B>);

Collections.copy(List<B>, List<A>); // KO

Collections.copy(List<B>, List<C>);

Collections.copy(List<C>, List<B>); // KO

Collections.copy(List<C>, List<A>); // KO

Collections.copy(List<C>, List<C>);

public class A {

}

public class B extends A {

}

public class C extends B {

}

void forEach(Consumer<? super T> action)

List<Double> temperature = Arrays.asList(20.0, 22.0, 22.5);

temperature.forEach(System.out::println);

void sort(Comparator<? super E> c)

List<Double> temperature = Arrays.asList(20.0, 22.0, 22.5);

temperature.sort((a, b) -> a > b ? -1 : 1);

boolean removeIf(Predicate<? super E> filter)

List<Double> temperature = Arrays.asList(20.0, 22.0, 22.5);

temperature.removeIf(s -> s > 22);

void replaceAll(UnaryOperator<E> operator)

List<Double> temperature = Arrays.asList(20.0, 22.0, 22.5);

temperature.replaceAll(s -> Math.pow(s, 0.5));

void forEach(BiConsumer<? super K, ? super V> action)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.forEach((a, b) -> System.out.println(a + " wrote " + b + " books"));

V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.compute("Clive Cussler", (a, b) -> b + 1);

// If the compute function returns null then the entry for that key is removed

// from the map. If the key is not present then a new entry is added.

V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.computeIfAbsent("Agatha Christie", b -> b.length());

// The entry is added only if the computed value is not null.

V computeIfPresent(K key,

BiFunction<? super K, ? super V, ? extends V> remappingFunction)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.computeIfPresent("Tom Clancy", (a, b) -> b + 1);

// Note that this function also removes an element if the new value computed from

// the passed lambda expression is null.

V getOrDefault(Object key, V defaultValue)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.getOrDefault("AuthorA", 0)

V merge(K key, V value,

BiFunction<? super V, ? super V, ? extends V> remappingFunction)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

authorBooks.merge("AuthorB", 1, (a, b) -> a + b);

System.out.println(authorBooks.get("AuthorB")); // 1

authorBooks.merge("AuthorB", 1, (a, b) -> a + b);

System.out.println(authorBooks.get("AuthorB")); // 2

V putIfAbsent(K key, V value)

Map<String , Integer> authorBooks = new HashMap<String , Integer>();

authorBooks.put("Robert Ludlum", 27);

authorBooks.put("Clive Cussler", 50);

authorBooks.put("Tom Clancy", 17);

System.out.println(authorBooks.putIfAbsent("AuthorC", 2)); // null

System.out.println(authorBooks.putIfAbsent("AuthorC", 2)); // 2

boolean remove(Object key, Object value)

V replace(K key, V newValue)

boolean replace(K key, V oldValue, V newValue)

void replaceAll (BiFunction<? super K, ? super V, ? extends V> function)

8

Comparator<Person> comparator =

(p1, p2) -> p1.firstname.compareTo(p2.firstname);

Comparator<Person> comparator = Comparator.comparing(p -> p.lastname)

Comparator<Person> comparator = Comparator.comparing(Person::getLastname);

Comparator<Person> comparator = (p1, p2) -> {

int r = p1.lastname.compareTo(p2.lastname);

if (r != 0)

return r;

return p1.firstname.compareTo(p2.firstname);

};

Comparator<Person> comparator4 = Comparator

.comparing(Person::getLastname)

.thenComparing(Person::getFirstname);

Comparator<Person> comparator = Comparator

.comparing(Person::getLastname)

.reverse()

.thenComparing(Person::getFirstname);

9

// The result won't be always the same

Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());

stream.parallel().map(e -> {

if (seen.add(e)) return 0; else return e;

}

);

// with a stateless lambda expression the results would

always be the same.

IntStream.range(0,5).parallel().map(x -> x * 2).toArray()

// use reduction instead of mutable accumulators

int sum = numbers.stream().reduce(0, Integer::sum);

int sumOfWeights = widgets.stream()

.reduce(0,

(sum, b) -> sum + b.getWeight())

Integer::sum);

http://gotocon.com/dl/goto-amsterdam-2014/slides/PaulSandoz_PerchanceToStreamWithJava8.pdf

Source Decomposibility Characteristics

ArrayList (and arrays) Excellent SIZED, ORDERED

LinkedList Poor SIZED, ORDERED

HashSet Good SIZED, DISTINCT

TreeSet Good SIZED, DISTINCT, SORTED, ORDERED

IntStream.range() Excellent SIZED, DISTINCT, SORTED, ORDERED

Stream.iterate() Poor ORDERED

BufferedReader.lines() Poor ORDERED

SplittableRandom.ints() Excellent

String<String> stream = Arrays.asList("a", "b", "c").stream();

String<String> stream = Stream.of("a", "b", "c")

Stream<String> stream = Files.lines(Paths.get(uri));

10

String<String> stream = Arrays.asList("a", "b", "c").stream();

String<String> stream = Stream.of("a", "b", "c")

Stream<String> stream = Files.lines(Paths.get(uri));

collection.stream();

collection.parellelStream();

static <T> Stream<T> generate(Supplier<T> s)

static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)

static <T> Stream<T> concat(Stream<? extends T> a,

Stream<? extends T> b)

static <T> Stream<T> of(T... values)

static <T> Stream<T> empty()

Stream<T> limit(long maxSize)

Stream<T> distinct()

Stream<T> filter(Predicate<? super T> predicate)

<R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)

DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper)

IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper)

LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper)

<R> Stream<R> map(Function<? super T,? extends R> mapper)

DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper)

IntStream mapToInt(ToIntFunction<? super T> mapper)

LongStream mapToLong(ToLongFunction<? super T> mapper)

long count()

boolean allMatch(Predicate<? super T> predicate)

boolean anyMatch(Predicate<? super T> predicate)

boolean noneMatch(Predicate<? super T> predicate)

Optional<T> findAny()

Optional<T> findFirst()

Optional<T> max(Comparator<? super T> comparator)

Optional<T> min(Comparator<? super T> comparator)

Optional<T> reduce(BinaryOperator<T> accumulator)

T reduce(T identity, BinaryOperator<T> accumulator)

<U> U reduce(U identity,

BiFunction<U,? super T,U> accumulator,

BinaryOperator<U> combiner)

Object[] toArray()

<A> A[] toArray(IntFunction<A[]> generator)

void forEach(Consumer<? super T> action)

void forEachOrdered(Consumer<? super T> action)

<R,A> R collect(Collector<? super T,A,R> collector)

<R> R collect(Supplier<R> supplier,

BiConsumer<R,? super T> accumulator,

BiConsumer<R,R> combiner)

public void closure() {

List<Supplier<Integer>> list = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

list.add(() -> i);

}

}

public void closure() {

List<Supplier<Integer>> list = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

list.add(() -> i);

}

}

DOES NOT COMPILEThe value of « i » changes along the way

public void closure() {

List<Supplier<Integer>> list = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

final int j = i;

list.add(() -> j);

}

list.forEach((e) -> System.out.print(e.get())); // 12345

}

COMPILEA new « j » variable is created at each iteration

public void closure() {

List<Supplier<Integer>> list = new ArrayList<>();

for (int i = 1; i <= 5; i++) {

final int j = i;

list.add(() -> j);

}

list.forEach((e) -> System.out.print(e.get())); // 12345

}

The « final » keyword is not mandatory as the value of « j » is set once and for allIn this example « j » IS EFFECTIVELY FINAL

public void closure() {

List<Supplier<Integer>> list =

IntStream.range(1, 6)

.mapToObj((i) -> (Supplier<Integer>) () -> i)

.collect(Collectors.toList());

list.forEach((e) -> System.out.print(e.get())); // 12345

}

public class Closure {

private int index = 1;

public void closure() {

List<Supplier<Integer>> list =

IntStream.range(-5, 0)

.mapToObj((i) -> (Supplier<Integer>) () -> index++)

.collect(Collectors.toList());

list.forEach((e) -> System.out.print(e.get())); // 12345

}

}

http://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html

11

http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.htmlhttp://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html