Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Geekout] Java 8 Puzzlers: The Strange, The Bizarre, And The Wonderful

[Geekout] Java 8 Puzzlers: The Strange, The Bizarre, And The Wonderful

Mikalai and Viktor aren’t sure about you, but working with Java 8 made both of the speakers lose their sleep (or was it the jetlag?). If you still haven’t reached the level of Brian Goetz in mastering lambdas and strings, this talk is for you. And if you think you have, we have some bad news for you, you should attend as well.
Mikalai and Viktor will show you some surprising, bizarre, and inconceivable parts of Java 8 and make sure that you won’t be (too) surprised when it hits you in production.
As with any other puzzlers talk, there will be two speakers, lots of puzzling questions, answers by the audience, T-shirts flying around, and a lot of fun, all for one purpose—to help you better understand Java 8.

Viktor Gamov

June 10, 2016
Tweet

More Decks by Viktor Gamov

Other Decks in Technology

Transcript

  1. 1. Two entertaining guys on stage 2. Funny Puzzling questions

    3. You think and vote 4. Awesome t-shirts fly in the air 5. Official twitter handle! JA VA8puzzlers
  2. What will be the output? A. milk/bread/sausage B. milk/bread/sausage/eggs, don’t

    forget eggs! C. milk/bread/sausage/ConcurrentModificationException D. ConcurrentModificationException List<String> list = new ArrayList<>(); list.add("milk"); list.add("bread"); list.add("sausage"); Stream<String> stream = list.stream(); list.add("eggs, don’t forget eggs!"); stream.forEach(System.out::println);
  3. Late binding, duh… List<String> list = new ArrayList<>(); list.add("milk"); list.add("bread");

    list.add("sausage"); Stream<String> stream = list.stream(); list.add("eggs, don’t forget eggs!"); stream.forEach(System.out::println);
  4. Late binding, duh… List<String> list = new ArrayList<>(); list.add("milk"); list.add("bread");

    list.add("sausage"); Stream<String> stream = list.stream(); list.add("eggs, don’t forget eggs!"); stream.forEach(System.out::println);
  5. What will be the output? A. milk/bread/sausage B. milk/bread/eggs, don’t

    forget eggs! C. milk/bread/ConcurrentModificationException D. ConcurrentModificationException List<String> list = new ArrayList<>(); list.add("milk"); list.add("bread"); list.add("sausage"); list = list.subList(0, 2); //No sausage, please! Stream<String> stream = list.stream(); list.add("eggs, don’t forget eggs!"); stream.forEach(System.out::println);
  6. What’s the difference between 1 and 2? A. 1 compiles,

    2 does not B. 2 compiles, 1 does not C. Same same, both work fine D. Same same, both won’t compile public void killAll(){ ExecutorService ex = Executors.newSingleThreadExecutor(); List<String> sentence = Arrays.asList("Punish"); ex.submit(() -> Files.write(Paths.get("Sentence.txt"), sentence) ); // 1 ex.submit(() -> { Files.write(Paths.get("Sentence.txt"), sentence); }); // 2 }
  7. What’s the difference between 1 and 2? A. 1 compiles,

    2 does not B. 2 compiles, 1 does not C. Same same, both work fine D. Same same, both won’t compile public void killAll(){ ExecutorService ex = Executors.newSingleThreadExecutor(); List<String> sentence = Arrays.asList("Punish"); ex.submit(() -> Files.write(Paths.get("Sentence.txt"), sentence) ); // 1 ex.submit(() -> { Files.write(Paths.get("Sentence.txt"), sentence); }); // 2 }
  8. public void killAll(){ ExecutorService ex = Executors.newSingleThreadExecutor(); List<String> sentence =

    Arrays.asList("Punish"); ex.submit(() -> Files.write(Paths.get("Sentence.txt"), sentence) ); // 1 ex.submit(() -> { Files.write(Paths.get("Sentence.txt"), sentence); }); // 2 } @FunctionalInterface public interface Runnable { public abstract void run(); } @FunctionalInterface public interface Callable<V> { V call() throws Exception; }
  9. How that will work? A. Compilation error B. Runtime Exception

    C. 3 D. Something else System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get() );
  10. How about now? A. −3 B. −1 C. 0 D.

    Something else System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get() );
  11. How about now? A. −3 B. −1 C. 0 D.

    Something else System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get() );
  12. • Math.max(−3, −2) = −2 < 0 à −3 <

    −2, selecting −2 • Math.max(−2, −1) = −1 < 0 à −2 < −1, selecting −1 • Math.max(−1, 0) = 0 à −1 == 0, keeping −1 • Math.max(−1, 1) = 1 > 0 à −1 > 1, keeping −1 • Math.max(−1, 2) = 2 > 0 à −1 > 2, keeping −1 • Math.max(−1, 3) = 3 > 0 à −1 > 3, keeping −1 Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get()
  13. What will happen? A. Maps will switch B. Both will

    become oldSchool C. Both will become hipster D. Really?! That won’t even compile! Map<String, String> oldSchool = initOldSchoolStack(); // oldSchool = {buildTool=maven, lang=java, db=db2} Map<String, String> proper = initHipsterStack(); // proper = {buildTool=npm, lang=javascript, db=mongodb} oldSchool.replaceAll(proper::put);
  14. void replaceAll(BiFunction<? super K, ? super V, ? extends V>

    function) V put(K key, V value); Map interface oldSchool.replaceAll(proper::put);
  15. void replaceAll(BiFunction<? super K, ? super V, ? extends V>

    function) V put(K key, V value); Map interface final BiFunction<String, String, String> function = (key, value) -> proper.put(key, value); for (Map.Entry<String, String> entry : oldSchool.entrySet()) entry.setValue(function.apply(entry.getKey(), entry.getValue()));
  16. void replaceAll(BiFunction<? super K, ? super V, ? extends V>

    function) V put(K key, V value); Map interface final BiFunction<String, String, String> function = (key, value) -> proper.put(key, value); for (Map.Entry<String, String> entry : oldSchool.entrySet()) entry.setValue(function.apply(entry.getKey(), entry.getValue()));
  17. How many lines will be the same? List<String> kitties =

    Arrays.asList("Soft", "Warm", "Purr"); Comparator<String> kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder()); System.out.println(Collections.max(kitties, kittiesComparator)); System.out.println(kitties.stream().collect(Collectors.maxBy(kittiesComparator)).get()); System.out.println(kitties.stream().max(kittiesComparator).get()); A. All lines the same B. Two lines the same C. All different D. Four different
  18. How about now? List<String> kitties = Arrays.asList("Soft", null, "Purr"); Comparator<String>

    kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder()); System.out.println(Collections.max(kitties, kittiesComparator)); System.out.println(kitties.stream().collect(Collectors.maxBy(kittiesComparator)).get()); System.out.println(kitties.stream().max(kittiesComparator).get()); A. All lines the same B. Two lines the same C. All different D. Four different
  19. How about now? List<String> kitties = Arrays.asList("Soft", null, "Purr"); Comparator<String>

    kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder()); System.out.println(Collections.max(kitties, kittiesComparator)); System.out.println(kitties.stream().collect(Collectors.maxBy(kittiesComparator)).get()); System.out.println(kitties.stream().max(kittiesComparator).get()); A. All lines the same B. Two lines the same C. All different D. Four different
  20. How to cast to a type without declaring it? interface

    Cat{ default void meow() {System.out.println("meow ");}} interface Dog{ default void bark() {System.out.println("woof ");}} public static void main(String[] args) { class Dogcat implements Dog, Cat{} test(new Dogcat()); } static void test(Object obj) { def x = (?)obj; x.meow (); x.bark (); }
  21. How to cast to a type without declaring it? static

    void test(Object obj) { // A. Will that work? Dog & Cat x = (Dog & Cat) obj; x.meow (); x.bark (); } static void test(Object obj) { // B. Will that work? ((Consumer<? extends Dog & Cat>)(x -> { x.meow (); x.bark (); })).accept((Dog & Cat)obj); } static void test(Object obj) { // C. Will that work? Optional.of((Dog & Cat) obj) .ifPresent(x -> { x.meow (); x.bark (); });} // D. You’re two sick bastards. interface Cat{ default void meow() {System.out.println(”meow");}} interface Dog{ default void bark() {System.out.println(”woof");}} public static void main(String[] args) { class Dogcat implements Dog, Cat{} test(new Dogcat()); }
  22. How to cast to a type without declaring it? static

    void test(Object obj) { // A. Will that work? Dog & Cat x = (Dog & Cat) obj; x.meow(); x.bark(); } static void test(Object obj) { // B. Will that work? ((Consumer<? extends Dog & Cat>)(x -> { x.meow(); x.bark(); })).accept((Dog & Cat)obj); } static void test(Object obj) { // C. Will that work? Optional.of((Dog & Cat) obj) .ifPresent(x -> { x.meow(); x.bark(); });} // D. You’re two sick bastards. interface Cat{ default void meow() {System.out.println(”meow");}} interface Dog{ default void bark() {System.out.println(”woof");}} public static void main(String[] args) { static class Dogcat implements Dog, Cat{} test(new Dogcat()); }
  23. static void test(Object obj) { // C. Will that work?

    Optional.of((Dog & Cat) obj) .ifPresent(x -> { x.meow(); x.bark(); });}
  24. What will be the output? 1. HOTEL ECHO LIMA LIMA

    OSCAR/ HOTEL ECHO LIMA LIMA OSCAR 2. HELLO / HOTEL ECHO LIMA LIMA OSCAR 3. HOTEL ECHO LIMA LIMA OSCAR/ HELLO 4. HELLO/HELLO public class Test { String str; void run() { str = "hello "; Supplier<String> s1 = str::toUpperCase; Supplier<String> s2 = () -> str.toUpperCase(); str = "Hotel Echo Lima Lima Oscar "; System.out.println(s1.get()); System.out.println(s2.get()); } }
  25. What will be the output? 1. HOTEL ECHO LIMA LIMA

    OSCAR/ HOTEL ECHO LIMA LIMA OSCAR 2. HELLO / HOTEL ECHO LIMA LIMA OSCAR 3. HOTEL ECHO LIMA LIMA OSCAR/ HELLO 4. HELLO/HELLO public class Test { String str; void run() { str = "hello"; Supplier<String> s1 = str::toUpperCase; Supplier<String> s2 = () -> str.toUpperCase(); str = "Hotel Echo Lima Lima Oscar"; System.out.println(s1.get()); System.out.println(s2.get()); } }
  26. What will happen? 1. ConcurrentModificationException 2. ArrayIndexOutOfBoundsException 3. NullPointerException 4.

    No exceptions, all good List<String> list = new ArrayList<>(Arrays.asList("Arnie", "Chuck", "Slay")); list.stream().forEach(x -> { if(x.equals("Chuck")) { list.remove(x); } });
  27. What will happen? A. ConcurrentModificationException B. ArrayIndexOutOfBoundsException C. NullPointerException D.

    No exceptions, all good List<String> list = new ArrayList<>(Arrays.asList("Arnie", "Chuck", "Slay")); list.stream().forEach(x -> { if(x.equals("Chuck")) { list.remove(x); } });
  28. Here’s why: stream().forEach() à spliterator().forEachRemaining() forEachRemaining checks for mod count

    once, in the end Removing element adds null to the end of the array: ["Arne", "Chuck", "Slay"] à ["Arne", "Slay", null] On the last iteration if(null.equals("Chuck")) fails with NPE (didn’t get to CME) Use list.removeIf("Chuck"::equals);
  29. System.out.println(Optional.of("rtfm").orElseGet(null)); System.out.println(Optional.empty().map(null).orElse("rtfm")); What will be the output? A. rtfm /

    rtfm B. rtfm / NullPointerException C. NullPointerException / NullPointerException D. NullPointerException / rtfm
  30. System.out.println(Optional.of("rtfm").orElseGet(null)); System.out.println(Optional.empty().map(null).orElse("rtfm")); What will be the output? A. rtfm /rtfm

    B. rtfm / NullPointerException C. NullPointerException / NullPointerException D. NullPointerException / rtfm
  31. - Write readable code! - Comment all the tricks -

    Sometimes it’s a bug - Static code analysis FTW - intellij IDEA! - Rtfm - Don’t abuse lambdas and streams!
  32. Did you like it? Praise us on twitter and in

    the feedback form! - java8puzzlers - gamussa - xpinjection Didn’t like it? /dev/null