T h e Da r k S i d e of Jav a 8 - JavaLand · 23/03/2019 The Dark Side of Java 8
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
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
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 3/90
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
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
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
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...
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...
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 �
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 11/90
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
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, (...)]
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
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);
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(...);
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)
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);
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);
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()
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.
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()
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 } } }
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
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"))); }
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();
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();
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
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();
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
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 32/90
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()
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
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
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
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"));
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
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
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 41/90
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+
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
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); }
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 45/90
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 46/90
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 48/90
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
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
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; }
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 }
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 }
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 :) }
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
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)
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); } }; }
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())));
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/
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
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
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™
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 (?)™
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);
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);
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.
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?
......
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;
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 (...)
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 -> {}));
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
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
23/03/2019 The Dark Side of Java 8
https://pivovarit.github.io/talks/java-8-dark-side/?print-pdf#/ 73/90
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());
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());
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
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
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)
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 // ...
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} // ...
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
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
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 ...
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]
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. */
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
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)
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 ...
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.
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