$30 off During Our Annual Pro Sale. View Details »

[Philly ETE] Java Puzzlers NG

[Philly ETE] Java Puzzlers NG

The more we work with Java 8, the more we go into the rabbit hole. Did they add all those streams, lambdas, monads, Optionals and CompletableFutures only to confuse us? It surely looks so! And Java 9 that heads our way brings even more of what we like the most, more puzzlers, of course! In this season we, as usual, have a great batch of the best Java WTF, great jokes to present them and great prizes for the winners!

Viktor Gamov

April 18, 2017
Tweet

More Decks by Viktor Gamov

Other Decks in Programming

Transcript

  1. This slide is intentionally left
    blank

    View Slide

  2. JAVA PUZZLERS NG
    DOWN THE RABBIT HOLE
    http://www.davidfloresmedia.com/philly-rocky-statue/

    View Slide

  3. @gAmUssA @hazelcast #jbreak #hazelcastjet
    > whoami

    View Slide

  4. @gAmUssA @hazelcast #jbreak #hazelcastjet
    Solutions Architect
    > whoami

    View Slide

  5. @gAmUssA @hazelcast #jbreak #hazelcastjet
    Solutions Architect
    Developer Advocate
    > whoami

    View Slide

  6. @gAmUssA @hazelcast #jbreak #hazelcastjet
    Solutions Architect
    Developer Advocate
    @gamussa in internetz
    > whoami

    View Slide

  7. @gAmUssA @hazelcast #jbreak #hazelcastjet
    Solutions Architect
    Developer Advocate
    @gamussa in internetz
    Please, follow me on Twitter
    > whoami

    View Slide

  8. @gAmUssA @hazelcast #jbreak #hazelcastjet
    Solutions Architect
    Developer Advocate
    @gamussa in internetz
    Please, follow me on Twitter
    I’m very interesting ©
    > whoami

    View Slide

  9. View Slide

  10. View Slide

  11. Developer Advocate @JFrog
    on the internetz
    Developer Advocate @Hazelcast
    @gAmUssA on the internetz

    View Slide

  12. CLICK AND HACK
    THE TYPE-IT BROTHERS

    View Slide

  13. @tagir_valeev
    @gamussa #PhillyETE

    View Slide

  14. @gamussa #PhillyETE

    View Slide

  15. @gamussa #PhillyETE

    View Slide

  16. @gamussa #PhillyETE

    View Slide

  17. View Slide

  18. 1. Two One entertaining guy on
    the stage

    View Slide

  19. 1. Two One entertaining guy on
    the stage
    2. Funny puzzling questions

    View Slide

  20. 1. Two One entertaining guy on
    the stage
    2. Funny puzzling questions
    3. You think and vote

    View Slide

  21. 1. Two One entertaining guy on
    the stage
    2. Funny puzzling questions
    3. You think and vote
    4.Official twitter hashtags
    #javapuzzlersng #PhillyETE

    View Slide

  22. FIRST RULE OF THE PUZZLERS:
    NO CHEATING!

    View Slide

  23. Which Java version are you on?
    @gamussa #PhillyETE

    View Slide

  24. Which Java version are you on?
    A. Java 7
    @gamussa #PhillyETE

    View Slide

  25. Which Java version are you on?
    A. Java 7
    B. Java 8
    @gamussa #PhillyETE

    View Slide

  26. Which Java version are you on?
    A. Java 7
    B. Java 8
    C. Java 9
    @gamussa #PhillyETE

    View Slide

  27. Which Java version are you on?
    A. Java 7
    B. Java 8
    C. Java 9
    D. Java 6
    @gamussa #PhillyETE

    View Slide

  28. Which Java version are you on?
    A. Java 7
    B. Java 8
    C. Java 9
    D. Java 6
    E. Java 5
    @gamussa #PhillyETE

    View Slide

  29. Which Java version are you on?
    A. Java 7
    B. Java 8
    C. Java 9
    D. Java 6
    E. Java 5
    F. Java 2
    @gamussa #PhillyETE

    View Slide

  30. Which Java version are you on?
    A. Java 7
    B. Java 8
    C. Java 9
    D. Java 6
    E. Java 5
    F. Java 2
    @gamussa #PhillyETE

    View Slide

  31. Watching the puzzlers like… #dafaq
    @gamussa #PhillyETE

    View Slide

  32. Watching the puzzlers like… #dafaq
    @gamussa #PhillyETE

    View Slide

  33. Everything works (or doesn't) 

    in the latest Java 8 and/or 9 update
    @gamussa #PhillyETE

    View Slide

  34. View Slide

  35. RUSSIAN HACKERS
    HACKING THE BANK

    View Slide

  36. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }


    View Slide

  37. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }

    A. IllegalArgumentException – can’t create semaphore with negative

    View Slide

  38. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }

    A. IllegalArgumentException – can’t create semaphore with negative
    B. UnsupportedOperationException – can’t drain when negative

    View Slide

  39. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }

    A. IllegalArgumentException – can’t create semaphore with negative
    B. UnsupportedOperationException – can’t drain when negative
    C. 0

    View Slide

  40. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }

    A. IllegalArgumentException – can’t create semaphore with negative
    B. UnsupportedOperationException – can’t drain when negative
    C. 0
    D. -42

    View Slide

  41. public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }

    A. IllegalArgumentException – can’t create semaphore with negative
    B. UnsupportedOperationException – can’t drain when negative
    C. 0
    D. -42

    View Slide

  42. @gamussa #PhillyETE

    View Slide

  43. @gamussa #PhillyETE

    View Slide

  44. @gamussa #PhillyETE

    View Slide

  45. A. IllegalArgumentException – can’t create semaphore with negative
    B. UnsupportedOperationException – can’t drain when negative
    C. 0
    D. -42
    public class PerfectRobbery {

    private Semaphore bankAccount = new Semaphore(-42);

    public static void main(String[] args) {

    PerfectRobbery perfectRobbery = new PerfectRobbery();

    perfectRobbery.takeAllMoney();

    perfectRobbery.checkBalance();

    }

    public void takeAllMoney(){

    bankAccount.drainPermits();

    }

    public void checkBalance(){

    System.out.println(bankAccount.availablePermits());

    }

    }


    View Slide

  46. @gamussa #PhillyETE

    View Slide

  47. @gamussa #PhillyETE

    View Slide

  48. @gamussa #PhillyETE

    View Slide

  49. Available
    -42?!
    @gamussa #PhillyETE

    View Slide

  50. Available
    -42?!
    @gamussa #PhillyETE

    View Slide

  51. @gamussa #PhillyETE

    View Slide

  52. Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  53. A. true/true
    Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  54. A. true/true
    B. true/false
    Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  55. A. true/true
    B. true/false
    C. false/true
    Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  56. A. true/true
    B. true/false
    C. false/true
    D. false/false
    Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  57. A. true/true
    B. true/false
    C. false/true
    D. false/false
    Collections.emptyList() == Collections.emptyList();

    Collections.emptyIterator() == Collections.emptyIterator();

    @gamussa #PhillyETE

    View Slide

  58. @gamussa #PhillyETE

    View Slide

  59. @gamussa #PhillyETE

    View Slide

  60. Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  61. A. true/true
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  62. A. true/true
    B. true/false
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  63. A. true/true
    B. true/false
    C. false/true
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  64. A. true/true
    B. true/false
    C. false/true
    D. false/false
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  65. A. true/true
    B. true/false
    C. false/true
    D. false/false
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();


    View Slide

  66. Singleton Strikes Back!
    @gamussa #PhillyETE

    View Slide

  67. Singleton Strikes Back!
    @gamussa #PhillyETE

    View Slide

  68. A. true/true
    B. true/false
    C. false/true
    D. false/false
    Spliterators.emptySpliterator() == Spliterators.emptySpliterator();

    Stream.empty() == Stream.empty();

    @gamussa #PhillyETE

    View Slide

  69. Even empty Stream has state!
    @gamussa #PhillyETE

    View Slide

  70. Even empty Stream has state!
    @gamussa #PhillyETE

    View Slide

  71. Even empty Stream has state!
    @gamussa #PhillyETE

    View Slide

  72. View Slide

  73. ”Identical”
    1. Has the same state
    2. Not related to “equals and hashcode” contract
    3. Not related to references to objects in
    memory
    @gamussa #PhillyETE

    View Slide

  74. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    @gamussa #PhillyETE

    View Slide

  75. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    @gamussa #PhillyETE

    View Slide

  76. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    B. Absolutely identical non-empty lists
    @gamussa #PhillyETE

    View Slide

  77. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    B. Absolutely identical non-empty lists
    C. Non-identical empty lists
    @gamussa #PhillyETE

    View Slide

  78. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    B. Absolutely identical non-empty lists
    C. Non-identical empty lists
    D. Non-identical non-empty lists
    @gamussa #PhillyETE

    View Slide

  79. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    B. Absolutely identical non-empty lists
    C. Non-identical empty lists
    D. Non-identical non-empty lists
    @gamussa #PhillyETE

    View Slide

  80. @gamussa #PhillyETE

    View Slide

  81. @gamussa #PhillyETE

    View Slide

  82. List[] twins = new List[2];

    Arrays.setAll(twins, ArrayList::new);

    A. Absolutely identical empty lists
    B. Absolutely identical non-empty lists
    C. Non-identical empty lists
    D. Non-identical non-empty lists
    @gamussa #PhillyETE

    View Slide

  83. @gamussa #PhillyETE

    View Slide

  84. @gamussa #PhillyETE

    View Slide

  85. @gamussa #PhillyETE

    View Slide

  86. How single is a Single Abstract Method
    Interface?
    @gamussa #PhillyETE

    View Slide

  87. public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  88. A. WTF?! ’Single’ means one, not three!
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  89. A. WTF?! ’Single’ means one, not three!
    B. Problem is with partyHard(T), remove it and it will work
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  90. A. WTF?! ’Single’ means one, not three!
    B. Problem is with partyHard(T), remove it and it will work
    C. Problem is the drinkIn methods, removing one of them and it will
    work
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  91. A. WTF?! ’Single’ means one, not three!
    B. Problem is with partyHard(T), remove it and it will work
    C. Problem is the drinkIn methods, removing one of them and it will
    work
    D. It will work fine! Both partyHard() and drinkIn() are merged in
    SingleAndHappy, leaving one abstract method
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  92. A. WTF?! ’Single’ means one, not three!
    B. Problem is with partyHard(T), remove it and it will work
    C. Problem is the drinkIn methods, removing one of them and it will
    work
    D. It will work fine! Both partyHard() and drinkIn() are merged in
    SingleAndHappy, leaving one abstract method
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  93. View Slide

  94. View Slide

  95. A. WTF?! ’Single’ means one, not three!
    B. Problem is with partyHard(T), remove it and it will work
    C. Problem are the drinkIn methods, removing it will leave one
    abstract method
    D. Yes! Both partyHard() and drinkIn() are merged in SingleAndHappy,
    leaving one abstract method
    public interface Single {

    default void partyHard(String songName) { System.out.println(songName); }

    void partyHard(T songName);

    void drinkIn(T drinkName);

    void drinkIn(String dringName);


    }

    @FunctionalInterface

    public interface SingleAndHappy extends Single { }
    @gamussa #PhillyETE

    View Slide

  96. @gamussa #PhillyETE

    View Slide

  97. RUSSIAN HACKERS
    STILL TRYING TO HACK THE BANK

    View Slide

  98. Hacking the bank
    ☑Bank software written in Java
    ☑Hack into it
    ☑Analyze the accounts
    @gamussa #PhillyETE

    View Slide

  99. Given the code above, which statement is wrong:
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  100. Given the code above, which statement is wrong:
    A. The Set is ordered by hashcode
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  101. Given the code above, which statement is wrong:
    A. The Set is ordered by hashcode
    B. The order is predictable across multiple runs of the JVM on the same machine
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  102. Given the code above, which statement is wrong:
    A. The Set is ordered by hashcode
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  103. Given the code above, which statement is wrong:
    A. The Set is ordered by hashcode
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  104. Given the code above, which statement is wrong:
    A. The Set is ordered by hashcode
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  105. View Slide

  106. View Slide

  107. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts= new HashSet<>(Arrays.asList("Gates", "Buffett", "Bezos", "Zuckerberg"));

    System.out.println(”accounts= " + accounts);

    @gamussa #PhillyETE

    View Slide

  108. public boolean add(E e) {

    return map.put(e, PRESENT)==null;

    }
    @gamussa #PhillyETE

    View Slide

  109. Your turn, FBI
    @gamussa #PhillyETE

    View Slide

  110. View Slide

  111. Given the code above, which statement is wrong:
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  112. Given the code above, which statement is wrong:
    A. The Set is ordered
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  113. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  114. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  115. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  116. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  117. @gamussa #PhillyETE

    View Slide

  118. @gamussa #PhillyETE

    View Slide

  119. @gamussa #PhillyETE

    View Slide

  120. Given the code above, which statement is wrong:
    A. The Set is ordered
    B. The order is predictable across multiple runs of the JVM on the same machine
    C. The order of elements in Set is not predictable
    D. Statements A & B are correct
    Set accounts = Set.of("Gates", "Buffett", "Bezos", "Zuckerberg");

    System.out.println(”accounts= " + accounts);
    @gamussa #PhillyETE

    View Slide

  121. private int probe(Object pe) {

    int idx = Math.floorMod(pe.hashCode() ^ SALT,
    elements.length);

    while (true) {

    E ee = elements[idx];

    if (ee == null) {

    return -idx - 1;

    } else if (pe.equals(ee)) {

    return idx;

    } else if (++idx == elements.length) {

    idx = 0;

    }

    }

    }
    @gamussa #PhillyETE

    View Slide

  122. Juggling Accident

    View Slide

  123. Juggling Accident

    View Slide

  124. What’s correct?
    @gamussa #PhillyETE

    View Slide

  125. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    @gamussa #PhillyETE

    View Slide

  126. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    B. If one of the dependencies was converted to a module,
    you have to declare it in module-info in order to use
    @gamussa #PhillyETE

    View Slide

  127. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    B. If one of the dependencies was converted to a module,
    you have to declare it in module-info in order to use
    C. Once you added the module-info to your project you
    have to declare the dependencies twice, in classpath
    and in module-info
    @gamussa #PhillyETE

    View Slide

  128. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    B. If one of the dependencies was converted to a module,
    you have to declare it in module-info in order to use
    C. Once you added the module-info to your project you
    have to declare the dependencies twice, in classpath
    and in module-info
    D. None of the above
    @gamussa #PhillyETE

    View Slide

  129. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    B. If one of the dependencies was converted to a module,
    you have to declare it in module-info in order to use
    C. Once you added the module-info to your project you
    have to declare the dependencies twice, in classpath
    and in module-info
    D. None of the above
    @gamussa #PhillyETE

    View Slide

  130. View Slide

  131. View Slide

  132. What’s correct?
    A. If you convert your application to module, classpath
    dependencies will still be resolved correctly
    B. If one of the dependencies was converted to a module,
    you have to declare it in module-info in order to use
    C. Once you added the module-info to your project you
    have to declare the dependencies twice, in classpath
    and in module-info
    D. None of the above
    @gamussa #PhillyETE

    View Slide

  133. @gamussa #PhillyETE

    View Slide

  134. @gamussa #PhillyETE

    View Slide

  135. View Slide

  136. static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  137. A. You killed them all
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  138. A. You killed them all
    B. You killed only even ones
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  139. A. You killed them all
    B. You killed only even ones
    C. They all survived
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  140. A. You killed them all
    B. You killed only even ones
    C. They all survived
    D. You killed only odd ones
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  141. A. You killed them all
    B. You killed only even ones
    C. They all survived
    D. You killed only odd ones
    E. All answers are correct
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  142. A. You killed them all
    B. You killed only even ones
    C. They all survived
    D. You killed only odd ones
    E. All answers are correct
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  143. @gamussa #PhillyETE

    View Slide

  144. @gamussa #PhillyETE

    View Slide

  145. A. You killed them all
    B. You killed only even ones
    C. They all survived
    D. You killed only odd ones
    E. All answers are correct
    static void killThemAll(Collection expendables) {

    Iterator heroes = expendables.iterator();

    heroes.forEachRemaining(e -> {

    if (heroes.hasNext()) {

    heroes.next();

    heroes.remove();

    }

    });

    System.out.println(expendables);

    }


    View Slide

  146. Don’t do that. Really, don’t.
    @gamussa #PhillyETE

    View Slide

  147. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    @gamussa #PhillyETE

    View Slide

  148. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    @gamussa #PhillyETE

    View Slide

  149. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    [S,S,S,V]
    @gamussa #PhillyETE

    View Slide

  150. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    [S,S,S,V]
    killThemAll(new ArrayDeque(Arrays.asList("N","S","W","S","L","S","L","V")));

    [N,S,W,S,L,S,L,V]
    @gamussa #PhillyETE

    View Slide

  151. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    [S,S,S,V]
    killThemAll(new ArrayDeque(Arrays.asList("N","S","W","S","L","S","L","V")));

    [N,S,W,S,L,S,L,V]
    @gamussa #PhillyETE

    View Slide

  152. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    [S,S,S,V]
    killThemAll(new ArrayDeque(Arrays.asList("N","S","W","S","L","S","L","V")));

    [N,S,W,S,L,S,L,V]
    killThemAll(new TreeSet(Arrays.asList("N","S","W","S","L","S","L","V")));
    @gamussa #PhillyETE

    View Slide

  153. Don’t do that. Really, don’t.
    killThemAll(new ArrayList(Arrays.asList("N","S","W","S","L","S","L","V")));

    []
    killThemAll(new LinkedList(Arrays.asList("N","S","W","S","L","S","L","V")));
    [S,S,S,V]
    killThemAll(new ArrayDeque(Arrays.asList("N","S","W","S","L","S","L","V")));

    [N,S,W,S,L,S,L,V]
    killThemAll(new TreeSet(Arrays.asList("N","S","W","S","L","S","L","V")));
    [N,W,L,L]
    @gamussa #PhillyETE

    View Slide

  154. Subtle Difference
    @gamussa #PhillyETE

    View Slide

  155. @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  156. A. Both work just fine
    @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  157. A. Both work just fine
    B. Lambda works, method ref fails
    @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  158. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  159. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    D. Won’t compile
    @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  160. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    D. Won’t compile
    @FunctionalInterface

    public interface OriginalPredicate {

    boolean test(T t);

    }
    OriginalPredicate lambda = (Object obj) -> "adidas".equals(obj);

    OriginalPredicate methodRef = "adidas"::equals;

    View Slide

  161. View Slide

  162. View Slide

  163. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    D. Not a functional interface, will fail on annotation processing
    @FunctionalInterface
    public interface CopyCatPredicate {

    boolean test(T t);

    }
    CopyCatPredicate lambda = (Object obj) -> "adadas".equals(obj);

    CopyCatPredicate methodRef = "adadas"::equals;


    View Slide

  164. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    D. Not a functional interface, will fail on annotation processing
    @FunctionalInterface
    public interface CopyCatPredicate {

    boolean test(T t);

    }
    CopyCatPredicate lambda = (Object obj) -> "adadas".equals(obj);

    CopyCatPredicate methodRef = "adadas"::equals;


    View Slide

  165. View Slide

  166. View Slide

  167. View Slide

  168. A. Both work just fine
    B. Lambda works, method ref fails
    C. Method ref works, lambda fails
    D. Not a functional interface, will fail on annotation processing
    @FunctionalInterface
    public interface CopyCatPredicate {

    boolean test(T t);

    }
    CopyCatPredicate lambda = (Object obj) -> "adadas".equals(obj);

    CopyCatPredicate methodRef = "adadas"::equals;


    View Slide

  169. @gamussa #PhillyETE

    View Slide

  170. A generic function type for a functional interface may be implemented by a
    method reference expression (§15.13), but not by a lambda expression
    (§15.27) as there is no syntax for generic lambda expressions.

    @gamussa #PhillyETE

    View Slide

  171. View Slide

  172. List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  173. A.[Data, Kirk, Spock]
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  174. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  175. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  176. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    D.[Data, Data, Kirk, Kirk, Spock, Spock]
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  177. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    D.[Data, Data, Kirk, Kirk, Spock, Spock]
    E.Are you nuts? Won’t compile! Data with Kirk?!
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  178. View Slide

  179. View Slide

  180. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    D.[Data, Data, Kirk, Kirk, Spock, Spock]
    E.Are you nuts? Won’t compile! Data with Kirk?!
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  181. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    D.[Data, Data, Kirk, Kirk, Spock, Spock]
    E.Are you nuts? Won’t compile! Data with Kirk?!
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  182. View Slide

  183. View Slide

  184. A.[Data, Kirk, Spock]
    B.[Spock, Kirk, Data, Data, Kirk, Spock]
    C.[Spock, Kirk, Data]
    D.[Data, Data, Kirk, Kirk, Spock, Spock]
    E.Are you nuts? Won’t compile! Data with Kirk?!
    List list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk",
    "Spock").sequential()

    .filter(new TreeSet<>()::add).collect(Collectors.toList());

    System.out.println(list);

    @gamussa #PhillyETE

    View Slide

  185. @gamussa #PhillyETE

    View Slide

  186. filter(new TreeSet<>()::add)
    @gamussa #PhillyETE

    View Slide

  187. filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))
    @gamussa #PhillyETE

    View Slide

  188. filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))
    !=
    @gamussa #PhillyETE

    View Slide

  189. filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))
    !=
    New instance is
    created every time!
    @gamussa #PhillyETE

    View Slide

  190. filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))
    !=
    New instance is
    created every time!
    Instance method is
    created once!
    @gamussa #PhillyETE

    View Slide

  191. @gamussa #PhillyETE

    View Slide

  192. Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  193. A. obvious / obvious
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  194. A. obvious / obvious
    B. obvious / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  195. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  196. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  197. @gamussa #PhillyETE

    View Slide

  198. @gamussa #PhillyETE

    View Slide

  199. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  200. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    Will never happen
    @gamussa #PhillyETE

    View Slide

  201. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    Will never happen
    Will never happen
    @gamussa #PhillyETE

    View Slide

  202. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    Will never happen
    Will never happen
    @gamussa #PhillyETE

    View Slide

  203. @gamussa #PhillyETE

    View Slide

  204. @gamussa #PhillyETE

    View Slide

  205. A. obvious / obvious
    B. obvious / NullPointerException
    C. NullPointerException / obvious
    D. NullPointerException / NullPointerException
    Optional.of("obvious").orElseGet(null);

    Optional.empty().map(null).orElse("obvious");
    @gamussa #PhillyETE

    View Slide

  206. @gamussa #PhillyETE

    View Slide

  207. @gamussa #PhillyETE

    View Slide

  208. @gamussa #PhillyETE

    View Slide

  209. @gamussa #PhillyETE

    View Slide

  210. Identical?
    @gamussa #PhillyETE

    View Slide

  211. When agentA == agentB?

    View Slide

  212. 1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    When agentA == agentB?

    View Slide

  213. 1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    When agentA == agentB?

    View Slide

  214. 1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  215. 1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  216. A.All
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  217. A.All
    B.3 and 4
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  218. A.All
    B.3 and 4
    C.Only 3
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  219. A.All
    B.3 and 4
    C.Only 3
    D.Other
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  220. A.All
    B.3 and 4
    C.Only 3
    D.Other
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  221. @gamussa #PhillyETE

    View Slide

  222. @gamussa #PhillyETE

    View Slide

  223. A.All
    B.3 and 4
    C.Only 3
    D.Other
    1. Consumer agentA = s -> System.out.println(s);

    Consumer agentB = s -> System.out.println(s);
    2. Consumer agentA = System.out::println;

    Consumer agentB = System.out::println;
    3. Supplier> supplier = () -> s -> System.out.println(s);

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    4. Supplier> supplier = () -> System.out::println;

    Consumer agentA = supplier.get();

    Consumer agentB = supplier.get();
    When agentA == agentB?

    View Slide

  224. Reuse is only possible for pure functions
    @gamussa #PhillyETE

    View Slide

  225. Reuse is only possible for pure functions
    Consumers accept parameters ==
    have state
    @gamussa #PhillyETE

    View Slide

  226. Reuse is only possible for pure functions
    Consumers accept parameters ==
    have state
    Supplier in 4 has state – the
    resolved method reference
    @gamussa #PhillyETE

    View Slide

  227. Conclusions
    @gamussa #PhillyETE

    View Slide

  228. View Slide

  229. -Write readable code!

    View Slide

  230. -Write readable code!
    -Comment all the tricks

    View Slide

  231. -Write readable code!
    -Comment all the tricks
    -Sometimes it’s just a bug

    View Slide

  232. -Write readable code!
    -Comment all the tricks
    -Sometimes it’s just a bug
    -Static code analysis FTW -
    IntelliJ IDEA!

    View Slide

  233. -Write readable code!
    -Comment all the tricks
    -Sometimes it’s just a bug
    -Static code analysis FTW -
    IntelliJ IDEA!
    -RTFM!

    View Slide

  234. -Write readable code!
    -Comment all the tricks
    -Sometimes it’s just a bug
    -Static code analysis FTW -
    IntelliJ IDEA!
    -RTFM!
    -Don’t abuse lambdas and
    streams!

    View Slide

  235. View Slide

  236. -Trust us, we have much
    more where those came
    from.

    View Slide

  237. -Trust us, we have much
    more where those came
    from.
    -Puzzlers? Gotchas? Fetal
    position inducing behavior?

    View Slide

  238. -Trust us, we have much
    more where those came
    from.
    -Puzzlers? Gotchas? Fetal
    position inducing behavior?
    [email protected]

    View Slide

  239. View Slide

  240. -Did you like it?

    View Slide

  241. -Did you like it?
    -Praise me on twitter!

    View Slide

  242. -Did you like it?
    -Praise me on twitter!
    -#javapuzzlersng #PhillyETE

    View Slide

  243. -Did you like it?
    -Praise me on twitter!
    -#javapuzzlersng #PhillyETE
    -@gamussa

    View Slide

  244. -Did you like it?
    -Praise me on twitter!
    -#javapuzzlersng #PhillyETE
    -@gamussa
    -Didn’t like it?

    View Slide

  245. -Did you like it?
    -Praise me on twitter!
    -#javapuzzlersng #PhillyETE
    -@gamussa
    -Didn’t like it?
    -/dev/null

    View Slide