T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

90
23/03/2019 The Dark Side of Java 8 https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 1/90 The Dark Side of Java 8 The Dark Side of Java 8 Grzegorz Piwowarek Grzegorz Piwowarek @pivovarit @pivovarit

Transcript of T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

Page 1: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 1/90

The Dark Side of Java 8The Dark Side of Java 8Grzegorz PiwowarekGrzegorz Piwowarek

@pivovarit@pivovarit

Page 2: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 2/90

{ { } }Lead Backend Engineer @ Lead Backend Engineer @

Trainer @ Trainer @ , ,

4comprehension.com4comprehension.comCasumoTechCasumoTech

Bottega IT MindsBottega IT MindsOS ContributorOS Contributor DZone MVBDZone MVB

Page 3: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 3/90

Page 4: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 4/90

Java 8Java 8

Page 5: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 5/90

https://twitter.com/mariofusco/status/957540001146986496

Page 6: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 6/90

Feature-driven -> Cadence-drivenFeature-driven -> Cadence-driven

Page 7: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 7/90

Feature-driven:Feature-driven:Java 7 - Strings in Switch StatementsJava 8 - Project LambdaJava 9 - Project JigSaw...

Page 8: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 8/90

Cadence-driven:Cadence-driven:Java 10 - 3.18Java 11 - 9.18Java 12 - 3.19...

Page 9: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 9/90

Java 12 - 3.19 �Java 12 - 3.19 �

Page 10: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 10/90

LTS Releases:LTS Releases:Java 7Java 7Java 8Java 8

Java 9Java 9Java 10Java 10

Java 11Java 11Java 12Java 12

......

Java 17Java 17

Page 11: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 11/90

Page 12: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 12/90

#1 Conditional Stream#1 Conditional StreamTerminationTermination

Page 13: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 13/90

List<LocalDate> getDates()

[2012-02-02, 2012-03-02, 2012-04-02, (...)]

Page 14: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 14/90

Task: take all dates before XXXTask: take all dates before XXX

Page 15: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 15/90

Works properly but evaluates the whole streamDoesn't work with in�nite streams

getDates().stream() .filter(date -> date.isBefore(LocalDate.of(2012, 4, 4))) .map(...) .forEach(System.out::println);

Page 16: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 16/90

2012-02-02, 2012-03-02, 2012-04-02,

-- POTENTIAL CUT OFF POINT --

2012-05-02, 2012-06-02, 2012-07-02, 2012-08-02, 2012-09-02, 2012-10-02, 2012-11-02, 2012-12-02, 2013-01-02, 2013-02-02, 2013-03-02, 2013-04-02, 2013-05-02, 2013-06-02, 2013-07-02, 2013-08-02, 2013-09-02, 2013-10-02, 2013-11-02, 2013-12-02,

...

getDates().stream() .peek(System.out::println) .filter(date -> date.isBefore(LocalDate.of(2012, 4, 4))) .map(...) .forEach(...);

Page 17: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 17/90

Solution: migrate to JDK9+Solution: migrate to JDK9+Stream#takeWhile/dropWhileStream#takeWhile/dropWhile

[JDK8] don't use Stream API if you want to be able to break out of it[JDK8] use limit() to cap the number of fetched elements (if applicable)

Page 18: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 18/90

getDates().stream() .filter(date -> date.isBefore(LocalDate.of(2014, 4, 4))) .map(...) .forEach(System.out::println);

Page 19: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 19/90

The stream terminates as soon the �rst mismatch is encountered

getDates().stream() .takeWhile(date -> date.isBefore(LocalDate.of(2014, 4, 4))) .map(...) .forEach(System.out::println);

Page 20: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 20/90

#2 Stream#�atMap()#2 Stream#�atMap()

Page 21: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 21/90

Streams ~ Lazy SequencesStreams ~ Lazy SequencesAs performant as imperative equivalents (time complexity)As performant as imperative equivalents (time complexity)

In theory.In theory.

Page 22: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 22/90

return getUsers().stream() .flatMap(u -> u.getAddresses().stream()) .filter(address -> address.contains("1")) .findAny()

Page 23: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 23/90

List<String> addresses = new ArrayList<>(); for (User u : getUsers()) { for (String address : u.getAddresses()) { if (address.contains("1")) { return address; // short-circuts the ongoing iteration } } }

Page 24: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 24/90

Not so true in practiceNot so true in practice

Page 25: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 25/90

Task: take a �rst encountered address of a �rstTask: take a �rst encountered address of a �rstencountered userencountered user

static List<User> getUsers() { // db fetch stub return List.of(new User(List.of("a1","a2","a3","a4","a5"))); }

Page 26: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 26/90

getUsers().stream() .flatMap(u -> u.getAddresses().stream()) .findAny();

Page 27: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 27/90

getUsers().stream() .flatMap(u -> u.getAddresses().stream()) .peek(System.out::println) .findAny();

Page 28: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 28/90

a1 a2 a3 a4 a5

https://bugs.openjdk.java.net/browse/JDK-8075939https://bugs.openjdk.java.net/browse/JDK-8075939https://bugs.openjdk.java.net/browse/JDK-8189234https://bugs.openjdk.java.net/browse/JDK-8189234

Page 29: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 29/90

getUsers().stream() .flatMap(u -> getAllAddresses(u)) // large/infinite stream .peek(System.out::println) .findAny();

Page 30: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 30/90

It gets worse once we start adding more operations:It gets worse once we start adding more operations:getUsers().stream() .flatMap(u -> u.getAddresses().stream()) .map(a -> { System.out.println("making a super expensive call now"); return 42; }) .findAny();

making a super expensive call now making a super expensive call now making a super expensive call now making a super expensive call now making a super expensive call now

Page 31: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 31/90

The causeThe cause

Page 32: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 32/90

Page 33: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 33/90

Solution: implement your own Spliterator-based lazySolution: implement your own Spliterator-based lazy�atMap()�atMap()

Page 34: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 34/90

https://stackover�ow.com/a/32767282/2229438https://stackover�ow.com/a/32767282/2229438

Page 35: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 35/90

Practical Solution: migrate to JDK10+Practical Solution: migrate to JDK10+JDK-8 Solution: don't use Stream API if you need nested collections to be evaluated lazilyJDK-9 Solution: see above

http://hg.openjdk.java.net/jdk/jdk10/rev/fca88bbbafb9http://hg.openjdk.java.net/jdk/jdk10/rev/fca88bbbafb9

Page 36: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 36/90

#3 JDK9 Stream#takeWhile#3 JDK9 Stream#takeWhile

Page 37: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 37/90

List<List<String>> list = List.of( List.of("1", "2"), List.of("3", "4", "5", "6", "7"));

Page 38: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 38/90

list.stream() .flatMap(Collection::stream) .forEach(System.out::println);

1 2 3 4 5 6 7

Page 39: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 39/90

Stream.of("1", "2", "3", "4", "5", "6", "7") .takeWhile(i -> !i.equals("4")) .forEach(System.out::println);

1 2 3

Page 40: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 40/90

List<List<String>> list = List.of( List.of("1", "2"), List.of("3", "4", "5", "6", "7")); list.stream() .flatMap(Collection::stream) .takeWhile(i -> !i.equals("4")) .forEach(System.out::println);

1 2 3 5 6 7

Page 41: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 41/90

Page 42: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 42/90

Solution: migrate to JDK10+Solution: migrate to JDK10+

Page 43: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 43/90

#4 Lambda Expressions vs.#4 Lambda Expressions vs.Checked ExceptionsChecked Exceptions

Page 44: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 44/90

java.util.function.Functionjava.util.function.Function@FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); }

Page 45: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 45/90

Page 46: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 46/90

Page 47: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 47/90

Solution: use helper wrappersSolution: use helper wrappersgetUsers().stream() .map(unchecked(u -> new URL(u.webpage))) .collect(Collectors.toList());

https://github.com/pivovarit/throwing-functionhttps://github.com/pivovarit/throwing-function

Page 48: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 48/90

Page 49: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 49/90

A bound of the form “throws α” is purely informational: it directsresolution to optimize the instantiation of “α” so that, if

possible, it is not a checked exception type. (…)

Otherwise, if the bound set contains “throws αi”, and the properupper bounds of “αi” are, at most, Exception, Throwable, and

Object, then Ti = RuntimeException.https://docs.oracle.com/javase/specs/jls/se8/html/jls-18.htmlhttps://docs.oracle.com/javase/specs/jls/se8/html/jls-18.html

Page 50: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 50/90

Simply put:Simply put:Every T in “<T extends Throwable>” is generously inferred to be

a RuntimeException if a more speci�c type can't be inferred.http://mail.openjdk.java.net/pipermail/lambda-dev/2013-February/007981.htmlhttp://mail.openjdk.java.net/pipermail/lambda-dev/2013-February/007981.html

Page 51: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 51/90

static void rethrow(Exception t) throws Exception { throw t; }

Page 52: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 52/90

static <T extends Exception> void rethrow(Exception t) throws T { throw t; // Unhandled exception: java.lang.Exception }

Page 53: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 53/90

static <T extends Exception> void rethrow(Exception t) throws T { throw (T) t; // Just cast it, #YOLO }

Page 54: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 54/90

public static void main(String[] args) { rethrow(new Exception(":>")); // no try-catch needed :) }

Page 55: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 55/90

Let's put that into practiceLet's put that into practice

Page 56: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 56/90

public interface ThrowingFunction<T, R> { R apply(T t) throws Exception; }

static <T, R> Function<T, R> sneaky(ThrowingFunction<T, R> f)

Page 57: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 57/90

static <T, R> Function<T, R> sneaky(ThrowingFunction<T, R> f) { return t -> { try { return f.apply(t); } catch (Exception ex) { return ThrowingFunction.sneakyThrow(ex); } }; }

Page 58: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 58/90

getUsers().stream() .map(sneaky(u -> new URL(u.webpage))) .map(sneaky(url -> url.openConnection()) .map(sneaky(c -> c.getInputStream())));

Page 59: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 59/90

http://4comprehension.com/sneakily-throwing-exceptions-in-lambda-expressions-in-java/http://4comprehension.com/sneakily-throwing-exceptions-in-lambda-expressions-in-java/

Page 60: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 60/90

Just because you don’t like the rules, doesn’t mean its a goodidea to take the law into your own hands. Your advice is

irresponsible because it places the convenience of the codewriter over the far more important considerations of

transparency and maintainability of the program. by Brian Goetz

https://stackover�ow.com/questions/19757300/java-8-lambda-streams-�lter-by-method-with-exception#comment54437053_19757456

Page 61: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 61/90

#5 Parallel Streams#5 Parallel Streams

Page 62: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 62/90

Parallel processing made easy™Parallel processing made easy™

Page 63: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 63/90

Parallel processing made easy (?)™Parallel processing made easy (?)™

Page 64: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 64/90

SequentialSequentialgetDates().stream() .map(...) .forEach(System.out::println);

Page 65: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 65/90

ParallelParallelgetDates().parallelStream() .map(...) .forEach(System.out::println);

Page 66: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 66/90

Ctrl + RCtrl + R

Not a very good idea.Not a very good idea.

Page 67: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 67/90

Multiple questions arise:Multiple questions arise:...but where are those tasks run?...but where are those tasks run?

...in the cloud?...in the cloud?...in the blockchain?...in the blockchain?

...how to provide a custom thread pool?...how to provide a custom thread pool?...what's the maximum number of tasks executed in parallel?...what's the maximum number of tasks executed in parallel?

......

Page 68: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 68/90

Code inspection reveals:Code inspection reveals:

Implementation detailA thread pool that is used for execution of parallel streams is unspeci�ed

static final ForkJoinPool common;

Page 69: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 69/90

public final ForkJoinTask<V> fork()

Arranges to asynchronously execute this task in the pool thecurrent task is running in (...)

Page 70: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 70/90

The size of the computation will be in proportion to the common pool and notThe size of the computation will be in proportion to the common pool and notthe custom pool.the custom pool.

Fixed in JDK10 - https://bugs.openjdk.java.net/browse/JDK-8190974Fixed in JDK10 - https://bugs.openjdk.java.net/browse/JDK-8190974

ForkJoinPool customPool = new ForkJoinPool(42); customPool.submit( () -> getDates().parallelStream().forEach(e -> {}));

Page 71: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 71/90

ForkJoinPool Settings:ForkJoinPool Settings:The parallelism levelForkJoinWorkerThreadFactoryUncaughtExceptionHandlerasyncMode

Since JDK 9:Since JDK 9:corePoolSizemaximumPoolSizeminimumRunnablesaturation allowedkeepAliveTime

Page 72: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 72/90

Note, however, that this technique of submitting a task to afork-join pool to run the parallel stream in that pool is an

implementation “trick” and is not guaranteed to work. by Stuart Marks

https://stackover�ow.com/questions/28985704/parallel-stream-from-a-hashset-doesnt-run-in-parallel/29272776#29272776

Page 73: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 73/90

Page 74: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 74/90

Which is faster? Sequential or Parallel?Which is faster? Sequential or Parallel?SequentialSequential

Random rand = new Random(); int[] array = new int[90000000]; Arrays.stream(array) .map(i -> rand.nextInt()) .boxed() .collect(Collectors.toList());

Page 75: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 75/90

Which is faster? Sequential or Parallel?Which is faster? Sequential or Parallel?ParallelParallel

Random rand = new Random(); int[] array = new int[90000000]; Arrays.stream(array).parallel() .map(i -> rand.nextInt()) .boxed() .collect(Collectors.toList());

Page 76: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 76/90

Parallel - doesn't always mean fasterParallel - doesn't always mean faster

Page 77: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 77/90

#6 Stream#generate#6 Stream#generate

Page 78: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 78/90

/** * Returns an infinite sequential unordered stream where each element is * generated by the provided {@code Supplier}. This is suitable for * generating constant streams, streams of random elements, etc. * * @param <T> the type of stream elements * @param s the {@code Supplier} of generated elements * @return a new infinite sequential unordered {@code Stream} */ public static<T> Stream<T> generate(Supplier<T> s)

Page 79: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 79/90

Stream.generate(() -> 42) .forEach(System.out::println); // 42 // 42 // 42 // ...

Page 80: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 80/90

Stream.generate(rand::nextInt) .forEach(System.out::println); // ${some.random.value1} // ${some.random.value2} // ${some.random.value3} // ...

Page 81: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 81/90

Stream.generate(new Supplier<Integer>() { private int value; @Override public Integer get() { return value++; }}) .limit(8) .forEach(System.out::println);

1 2 3 4 5 6 7 8

Page 82: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 82/90

Stream.generate(new Supplier<Integer>() { private int value; @Override public Integer get() { return value++; }}).parallel() .limit(8) .forEach(System.out::println);

0 2 4 7 6 8 1 3

Page 83: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 83/90

Stream.generate(new Supplier<Integer>() { private AtomicInteger value = new AtomicInteger(); @Override public Integer get() { return value.getAndIncrement(); }}).parallel() .limit(20) .forEach(System.out::println);

0 1 2 3 4 5 7 6 ...

Page 84: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 84/90

List<Integer> result = Stream.generate(new Supplier<Integer>() { private final AtomicInteger value = new AtomicInteger(); @Override public Integer get() { return value.getAndIncrement(); }}) .parallel() .peek(System.out::println) .limit(4) .collect(Collectors.toList());

i " "// 0 // 6 // 7 // 5 // 3 // 4 // 2 // 1 // 8 // 9 results: [5, 6, 0, 7]

Page 85: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 85/90

/** * Returns an in�nite sequential UNORDERED stream whereeach element is * generated by the provided Supplier. */

Page 86: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 86/90

#7 Optional vs Option#7 Optional vs Option

Page 87: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 87/90

Nulls are interpreted by Optional as Optional.empty()

User user = ... Optional.ofNullable(user) .map(o -> o.getAddress()) // getAddress() returns null .ifPresent(System.out::println); //

scala> Some(null)

Page 88: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 88/90

Two different results!

users.stream() .map(o -> o.getAddress()) .map(this::handleAddress) // handles null properly .findAny() ... users.stream() .findAny() .map(o -> o.getAddress()) .map(this::handleAddress) // null never makes it here ...

Page 89: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 89/90

Key takeaway:Key takeaway:Java sucks, let's PHPJava sucks, let's PHP

It's worth paying attention and migrating to new minor JDK releases. SmallIt's worth paying attention and migrating to new minor JDK releases. Smallthings matter.things matter.

Also, read the docs.Also, read the docs.

Page 90: T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8

23/03/2019 The Dark Side of Java 8

https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 90/90Twitter/GitHub: @pivovarit

Thank You!Thank You!

{ { } }

https://pivovarit.github.io/talks/java-8-dark-sidehttps://pivovarit.github.io/talks/java-8-dark-side

@[email protected]