java puzzlers ng s02: down the rabbit hole as presented at devnexus 2017

93
This slide is intentionally left blank

Upload: baruch-sadogursky

Post on 06-Apr-2017

578 views

Category:

Technology


1 download

TRANSCRIPT

This slide is intentionally left blank

Developer Advocate @JFrog@jbaruch on the internetz

Developer Advocate @Hazelcast@gAmUssA on the internetz

@tagir_valeev@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

1. Two entertaining guys on the stage

2. Funny puzzling questions3. You think and vote4.T-shirts are airborne5. Official twitter hashtags:

#javapuzzlersng#devnexus

Which Java version are you on?

A. Java 7B. Java 8C. Java 9D. Java 6E. Java 5F. Java 2

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Watching the puzzlers like… #dafaq

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

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

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

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 negativeB. UnsupportedOperationException – can’t drain when negativeC. 0D. -42

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. IllegalArgumentException – can’t create semaphore with negativeB. UnsupportedOperationException – can’t drain when negativeC. 0D. -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());}

}

Available -42?!

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Available -42?!

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. true/trueB. true/falseC. false/trueD. false/false

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

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. true/trueB. true/falseC. false/trueD. false/false

Spliterators.emptySpliterator() == Spliterators.emptySpliterator();Stream.empty() == Stream.empty();

Singleton Strikes Back!

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. true/trueB. true/falseC. false/trueD. false/false

Spliterators.emptySpliterator() == Spliterators.emptySpliterator();Stream.empty() == Stream.empty();

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Even empty Stream has state!

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

”Identical”

1. Has the same state

2. Not related to “equals and hashcode” contract

3. Not related to references to objects in memory

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

List[] twins = new List[2];Arrays.setAll(twins, ArrayList::new);

A. Absolutely identical empty listsB. Absolutely identical non-empty listsC. Non-identical empty listsD. Non-identical non-empty lists

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

List[] twins = new List[2];Arrays.setAll(twins, ArrayList::new);

A. Absolutely identical empty listsB. Absolutely identical non-empty listsC. Non-identical empty listsD. Non-identical non-empty lists

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

How single is a Single Abstract Method Interface?

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

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

workD. It will work fine! Both partyHard() and drinkIn() are merged in

SingleAndHappy, leaving one abstract method

public interface Single<T> {default void partyHard(String songName) { System.out.println(songName); }void partyHard(T songName);void drinkIn(T drinkName);void drinkIn(String dringName);

}@FunctionalInterfacepublic interface SingleAndHappy extends Single<String> { }

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. WTF?! ’Single’ means one, not three!B. Problem is with partyHard(T), remove it and it will workC. Problem are the drinkIn methods, removing it will leave one abstract

methodD. Yes! Both partyHard() and drinkIn() are merged in SingleAndHappy,

leaving one abstract method

public interface Single<T> {default void partyHard(String songName) { System.out.println(songName); }void partyHard(T songName);void drinkIn(T drinkName);void drinkIn(String dringName);

}@FunctionalInterfacepublic interface SingleAndHappy extends Single<String> { }

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Hacking the bank

☑Bank software written in Java☑Hack into it☑Analyze the accounts

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Given the code above, which statement is wrong:A. The Set is ordered by hashcodeB. The order is predictable across multiple runs of the JVM on the same machineC. The order of elements in Set is not predictableD. Statements A & B are correct

Set<String>accounts=newHashSet<>(Arrays.asList("Gates","Buffett","Bezos","Zuckerberg"));System.out.println(”accounts="+accounts);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Given the code above, which statement is wrong:A. The Set is orderedB. The order is predictable across multiple runs of the JVM on the same machineC. The order of elements in Set is not predictableD. Statements A & B are correct

Set<String>accounts=newHashSet<>(Arrays.asList("Gates","Buffett","Bezos","Zuckerberg"));System.out.println(”accounts="+accounts);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

public boolean add(E e) {return map.put(e, PRESENT)==null;

}

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Your turn, FBI

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Given the code above, which statement is wrong:A. The Set is orderedB. The order is predictable across multiple runs of the JVM on the same machineC. The order of elements in Set is not predictableD. Statements A & B are correct

Set<String>accounts=Set.of("Gates","Buffett","Bezos","Zuckerberg");System.out.println(”accounts="+accounts);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Given the code above, which statement is wrong:A. The Set is orderedB. The order is predictable across multiple runs of the JVM on the same machineC. The order of elements in Set is not predictableD. Statements A & B are correct

Set<String>accounts=Set.of("Gates","Buffett","Bezos","Zuckerberg");System.out.println(”accounts="+accounts);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

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

}}

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Juggling Accident

What’s correct?A. If you convert your application to module, classpath

dependencies will still be resolved correctlyB. If one of the dependencies was converted to a module, you

have to declare it in module-info in order to useC. 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@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

What’s correct?A. If you convert your application to module, classpath

dependencies will still be resolved correctlyB. If one of the dependencies was converted to a module, you

have to declare it in module-info in order to useC. 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@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. You killed them allB. You killed only even onesC. They all survivedD. You killed only odd onesE. All answers are correct

static void killThemAll(Collection<Hero> expendables) {Iterator<Hero> heroes = expendables.iterator();heroes.forEachRemaining(e -> {

if (heroes.hasNext()) {heroes.next();heroes.remove();

}});System.out.println(expendables);

}

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. You killed them allB. You killed only even onesC. They all survivedD. You killed only odd onesE. All answers are correct

static void killThemAll(Collection<Hero> expendables) {Iterator<Hero> heroes = expendables.iterator();heroes.forEachRemaining(e -> {

if (heroes.hasNext()) {heroes.next();heroes.remove();

}});System.out.println(expendables);

}

Don’t do that. Really, don’t.

killThemAll(new ArrayList<String>(Arrays.asList("N","S","W","S","L","S","L","V")));[]

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

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

killThemAll(new TreeSet<String>(Arrays.asList("N","S","W","S","L","S","L","V")));[N,W,L,L]

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Subtle Difference

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. Both work just fineB. Lambda works, method ref failsC. Method ref works, lambda failsD. Won’t compile

@FunctionalInterfacepublic interface OriginalPredicate<T> {

boolean test(T t);}

OriginalPredicate<Object> lambda = (Object obj) -> ”adidas".equals(obj);OriginalPredicate<Object> methodRef = ”adidas"::equals;

A. Both work just fineB. Lambda works, method ref failsC. Method ref works, lambda failsD. Not a functional interface, will fail on annotation processing

@FunctionalInterfacePublic interface CopyCatPredicate {

<T> boolean test(T t);}

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

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Agenericfunctiontypeforafunctionalinterfacemaybeimplementedbyamethodreferenceexpression(§15.13),butnotbyalambdaexpression(§15.27)asthereisnosyntaxforgenericlambdaexpressions.“

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A.[Data, Kirk, Spock]B.[Spock, Kirk, Data, Data, Kirk]C.[Spock, Kirk, Data]D.[Data, Data, Kirk, Kirk, Spock, Spock]E.Are you nuts? Won’t compile! Data with

Kirk?!

List<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()

.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A.[Data, Kirk, Spock]B.[Spock, Kirk, Data, Data, Kirk]C.[Spock, Kirk, Data]D.[Data, Data, Kirk, Kirk, Spock, Spock]E.Are you nuts? Won’t compile! Data with

Kirk?!

List<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()

.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A.[Data, Kirk, Spock]B.[Spock, Kirk, Data, Data, Kirk]C.[Spock, Kirk, Data]D.[Data, Data, Kirk, Kirk, Spock, Spock]E.Are you nuts? Won’t compile! Data with

Kirk?!

List<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()

.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))!=

Newinstanceiscreatedeverytime!

Instancemethodiscreatedonce!

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException

Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException

Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");

WillneverhappenWillneverhappen

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException

Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Identical?

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. AllB. 3 and 4C. Only 3D. Other

1. Consumer<String> agentA = s -> System.out.println(s);Consumer<String> agentB = s -> System.out.println(s);

2. Consumer<String> agentA = System.out::println;Consumer<String> agentB = System.out::println;

3. Supplier<Consumer<String>> supplier = () -> s -> System.out.println(s);Consumer<String> agentA = supplier.get();Consumer<String> agentB = supplier.get();

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

When agentA == agentB?

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

A. AllB. 3 and 4C. Only 3D. Other

1. Consumer<String> agentA = s -> System.out.println(s);Consumer<String> agentB = s -> System.out.println(s);

2. Consumer<String> agentA = System.out::println;Consumer<String> agentB = System.out::println;

3. Supplier<Consumer<String>> supplier = () -> s -> System.out.println(s);Consumer<String> agentA = supplier.get();Consumer<String> agentB = supplier.get();

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

When agentA == agentB?

Reuse is only possible for pure functions

•Consumers accept parameters == have state

•Supplier in 4 has state – the resolved method reference

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

Conclusions

@jbaruch@gamussa #devnexus http://jfrog.com/shownotes

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

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

-Puzzlers? Gotchas? Fetal position inducing behavior?

[email protected]

-Shownotes!-http://jfrog.com/shownotes-Slides-Video in 24 hours-Links-Ratings-Raffle! (come early)

-Did you like it?-Praise us on twitter!

-#javapuzzlersng #devnexus-@gamussa-@jbaruch

-Didn’t like it?-/dev/null