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. whoiam
    Senior Delivery Manager @EPAM
    @xpinjection on the internetz

    View full-size slide

  2. whoiam
    Señor Solutions Architect @Hazelcast
    @gAmUssA on the internetz

    View full-size slide

  3. 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

    View full-size slide

  4. Watching the puzzlers like… #dafaq

    View full-size slide

  5. Everything works (or doesn't) in the latest Java 8 update

    View full-size slide

  6. Broken Eggs Tale

    View full-size slide

  7. 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 list = new ArrayList<>();
    list.add("milk");
    list.add("bread");
    list.add("sausage");
    Stream stream = list.stream();
    list.add("eggs, don’t forget eggs!");
    stream.forEach(System.out::println);

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  10. What will be the output?
    A. milk/bread/sausage
    B. milk/bread/eggs, don’t forget eggs!
    C. milk/bread/ConcurrentModificationException
    D. ConcurrentModificationException
    List list = new ArrayList<>();
    list.add("milk");
    list.add("bread");
    list.add("sausage");
    list = list.subList(0, 2); //No sausage, please!
    Stream stream = list.stream();
    list.add("eggs, don’t forget eggs!");
    stream.forEach(System.out::println);

    View full-size slide

  11. Sometimes it’s just a bug…

    View full-size slide

  12. Execute ’em all

    View full-size slide

  13. 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 sentence = Arrays.asList("Punish");
    ex.submit(() -> Files.write(Paths.get("Sentence.txt"), sentence) ); // 1
    ex.submit(() -> { Files.write(Paths.get("Sentence.txt"), sentence); }); // 2
    }

    View full-size slide

  14. Semicolons are the evil!

    View full-size slide

  15. 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 sentence = Arrays.asList("Punish");
    ex.submit(() -> Files.write(Paths.get("Sentence.txt"), sentence) ); // 1
    ex.submit(() -> { Files.write(Paths.get("Sentence.txt"), sentence); }); // 2
    }

    View full-size slide

  16. public void killAll(){
    ExecutorService ex = Executors.newSingleThreadExecutor();
    List 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 call() throws Exception;
    }

    View full-size slide

  17. 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()
    );

    View full-size slide

  18. 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()
    );

    View full-size slide

  19. 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()
    );

    View full-size slide

  20. • 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()

    View full-size slide

  21. Let’s upgrade the stack!

    View full-size slide

  22. 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 oldSchool = initOldSchoolStack();
    // oldSchool = {buildTool=maven, lang=java, db=db2}
    Map proper = initHipsterStack();
    // proper = {buildTool=npm, lang=javascript, db=mongodb}
    oldSchool.replaceAll(proper::put);

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  26. How many lines will be the same?
    List kitties = Arrays.asList("Soft", "Warm", "Purr");
    Comparator 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

    View full-size slide

  27. How about now?
    List kitties = Arrays.asList("Soft", null, "Purr");
    Comparator 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

    View full-size slide

  28. How about now?
    List kitties = Arrays.asList("Soft", null, "Purr");
    Comparator 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

    View full-size slide

  29. List kitties = Arrays.asList("Soft", null, "Purr");
    Comparator kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());
    System.out.println(Collections.max(kitties, kittiesComparator));

    View full-size slide

  30. List kitties = Arrays.asList("Soft", null, "Purr");
    Comparator kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());
    System.out.println(kitties.stream().collect(Collectors.maxBy(kittiesComparator)).get());

    View full-size slide

  31. List kitties = Arrays.asList("Soft", null, "Purr");
    Comparator kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());
    System.out.println(kitties.stream().max(kittiesComparator).get());

    View full-size slide

  32. null
    Caught: java.lang.NoSuchElementException
    Caught: java.lang.NullPointerException
    Consistency, yeah.

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  36. Bill Gates explains how that works

    View full-size slide

  37. static void test(Object obj) {
    // C. Will that work?
    Optional.of((Dog & Cat) obj)
    .ifPresent(x -> {
    x.meow();
    x.bark();
    });}

    View full-size slide

  38. Viktor Gamov and Mikalai Alimenkou call customer
    service:

    View full-size slide

  39. 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 s1 = str::toUpperCase;
    Supplier s2 = () -> str.toUpperCase();
    str = "Hotel Echo Lima Lima Oscar ";
    System.out.println(s1.get());
    System.out.println(s2.get());
    }
    }

    View full-size slide

  40. 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 s1 = str::toUpperCase;
    Supplier s2 = () -> str.toUpperCase();
    str = "Hotel Echo Lima Lima Oscar";
    System.out.println(s1.get());
    System.out.println(s2.get());
    }
    }

    View full-size slide

  41. What will happen?
    1. ConcurrentModificationException
    2. ArrayIndexOutOfBoundsException
    3. NullPointerException
    4. No exceptions, all good
    List list = new ArrayList<>(Arrays.asList("Arnie", "Chuck", "Slay"));
    list.stream().forEach(x -> {
    if(x.equals("Chuck")) {
    list.remove(x);
    }
    });

    View full-size slide

  42. Java 8 vs Chuck Norris

    View full-size slide

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

    View full-size slide

  44. 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);

    View full-size slide

  45. 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

    View full-size slide

  46. 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

    View full-size slide

  47. - 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!

    View full-size slide

  48. Did you like it?
    Praise us on twitter and in the
    feedback form!
    - java8puzzlers
    - gamussa
    - xpinjection
    Didn’t like it?
    /dev/null

    View full-size slide