java 8 puzzlers [as presented at oscon 2016]

Post on 14-Feb-2017

596 Views

Category:

Software

4 Downloads

Preview:

Click to see full reader

TRANSCRIPT

JAVA 8 PUZZLERSTHE STRANGE, THE BIZARRE,

AND THE WONDERFUL

whoiam

Developer Advocate @JFrog@jbaruch on the internetz

whoiam

Solutions Architect @Hazelcast@gAmUssA on the internetz

CLICK AND HACK

THE TYPING BROTHERS

BTW,

1. Two entertaining guys on stage2. Funny Puzzling questions3. You think and vote4. Awesome t-shirts fly in the air5. Official twitter handle!

JAVA8puzzlers

FIRST RULE OF THE PUZZLERS:

NO CHEATING!

Watching the puzzlers like… #dafaq

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

Broken Eggs Tale

What will be the output?

A. milk/bread/sausageB. 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);

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

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

Going Vegan

What will be the output?

A. milk/bread/sausageB. milk/bread/eggs, don’t forget eggs!C. milk/bread/ConcurrentModificationExceptionD. 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);

ONE DOES NOT SIMPLY

GIVE UP ON SAUSAGES

Sometimes it’s just a bug…

Execute ’em all

What’s the difference between 1 and 2?

A. 1 compiles, 2 does notB. 2 compiles, 1 does notC. Same same, both work fineD. 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}

Semicolons are the evil!

What’s the difference between 1 and 2?

A. 1 compiles, 2 does notB. 2 compiles, 1 does notC. Same same, both work fineD. 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}

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}

@FunctionalInterfacepublic interface Runnable {

public abstract void run();}

@FunctionalInterfacepublic interface Callable<V> {

V call() throws Exception;}

Implicit return

Explicit return

Mad Max

How that will work?

A. Compilation errorB. Runtime ExceptionC. 3D. Something else

System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get());

How about now?

A. −3B. −1C. 0D. Something else

System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get());

How about now?

A. −3B. −1C. 0D. Something else

System.out.println( Stream.of(-3, -2, -1, 0, 1, 2, 3).max(Math::max).get());

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

Let’s upgrade the stack!

What will happen?

A.Maps will switchB.Both will become oldSchoolC.Both will become hipsterD.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=elastic}

oldSchool.replaceAll(proper::put);

void replaceAll(BiFunction<? super K, ? super V, ? extends V> function)

V put(K key, V value);

Map interface

oldSchool.replaceAll(proper::put);

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

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

ALL THE LISTS!

MAX

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 sameB.Two lines the sameC.All differentD.Four different

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 sameB.Two lines the sameC.All differentD.Four different

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 sameB.Two lines the sameC.All differentD.Four different

List<String> kitties = Arrays.asList("Soft", null, "Purr");Comparator<String> kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());

System.out.println(Collections.max(kitties, kittiesComparator));

List<String> kitties = Arrays.asList("Soft", null, "Purr");Comparator<String> kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());

System.out.println(kitties.stream().collect(Collectors.maxBy(kittiesComparator)).get());

List<String> kitties = Arrays.asList("Soft", null, "Purr");Comparator<String> kittiesComparator= Comparator.nullsLast(Comparator.naturalOrder());

System.out.println(kitties.stream().max(kittiesComparator).get());

nullCaught: java.lang.NoSuchElementExceptionCaught: java.lang.NullPointerException

Consistency, yeah.

Mutants

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 Dogcatimplements Dog, Cat{} test(new Dogcat());}

static void test(Object obj) {def x = (?)obj;x.meow ();x.bark ();

}

How to cast to a type without declaring it?

static void test(Object obj) { // A. Will that work?Dog& Catx = (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());}

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

Bill Gates explains how that works

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

Viktor Gamov and Baruch Sadogursky call customer service:

What will be the output?

1. HOTEL ECHO LIMA LIMA OSCAR/ HOTEL ECHO LIMA LIMA OSCAR

2. HELLO / HOTEL ECHO LIMA LIMA OSCAR3. HOTEL ECHO LIMA LIMA OSCAR/ HELLO4. 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()); }}

What will be the output?

1. HOTEL ECHO LIMA LIMA OSCAR/ HOTEL ECHO LIMA LIMA OSCAR

2. HELLO / HOTEL ECHO LIMA LIMA OSCAR3. HOTEL ECHO LIMA LIMA OSCAR/ HELLO4. 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()); }}

What will happen?

1. ConcurrentModificationException2. ArrayIndexOutOfBoundsException3. NullPointerException4. 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); }});

Java 8 vs Chuck Norris

What will happen?

A. ConcurrentModificationExceptionB. ArrayIndexOutOfBoundsExceptionC. NullPointerExceptionD. 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); }});

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

OR ELSE…

RTFM

System.out.println(Optional.of("rtfm").orElseGet(null));System.out.println(Optional.empty().map(null).orElse("rtfm"));

What will be the output?

A.rtfm / rtfmB.rtfm / NullPointerExceptionC.NullPointerException /

NullPointerExceptionD.NullPointerException / rtfm

System.out.println(Optional.of("rtfm").orElseGet(null));System.out.println(Optional.empty().map(null).orElse("rtfm"));

What will be the output?

A.rtfm /rtfmB.rtfm / NullPointerExceptionC.NullPointerException /

NullPointerExceptionD.NullPointerException / rtfm

Conclusions

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

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

- puzzlers jfrog.com

Did you like it?Praise us on twitter and in the feedback form!

- java8puzzlers- gamussa - jbaruch

Didn’t like it?/dev/null

top related