java puzzlers ng s02: down the rabbit hole as it was presented at the pittsburgh java meetup group
TRANSCRIPT
Developer Advocate @JFrog@jbaruch on the internetz
Solution Architect @Confluent@gAmUssA on the internetz
@tagir_valeev@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
1. Two entertaining guys on the stage
2. Funny puzzling questions3. You think and vote4.T-shirts are airborne5. Official twitter hashtag:
#javapuzzlersng
Which Java version are you on?
A. Java 7B. Java 8C. Java 9D. Java 6E. Java 5F. Java 2
@jbaruch http://jfrog.com/shownotes @gamussa
Watching the puzzlers like… #dafaq
@jbaruch http://jfrog.com/shownotes @gamussa
Everything works (or doesn't) in the latest Java 8 and/or 9 update
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
Available -42?!
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
A. true/trueB. true/falseC. false/trueD. false/false
Collections.emptyList() == Collections.emptyList();Collections.emptyIterator() == Collections.emptyIterator();
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
A. true/trueB. true/falseC. false/trueD. false/false
Spliterators.emptySpliterator() == Spliterators.emptySpliterator();Stream.empty() == Stream.empty();
Singleton Strikes Back!
@jbaruch http://jfrog.com/shownotes @gamussa
A. true/trueB. true/falseC. false/trueD. false/false
Spliterators.emptySpliterator() == Spliterators.emptySpliterator();Stream.empty() == Stream.empty();
@jbaruch http://jfrog.com/shownotes @gamussa
Even empty Stream has state!
@jbaruch http://jfrog.com/shownotes @gamussa
”Identical”
1. Has the same state
2. Not related to “equals and hashcode” contract
3. Not related to references to objects in memory
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
How single is a Single Abstract Method Interface?
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
Hacking the bank
☑Bank software written in Java☑Hack into it☑Analyze the accounts
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
public boolean add(E e) {return map.put(e, PRESENT)==null;
}
@jbaruch http://jfrog.com/shownotes @gamussa
Your turn, FBI
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
Subtle Difference
@jbaruch http://jfrog.com/shownotes @gamussa
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;
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 http://jfrog.com/shownotes @gamussa
Agenericfunctiontypeforafunctionalinterfacemaybeimplementedbyamethodreferenceexpression(§15.13),butnotbyalambdaexpression(§15.27)asthereisnosyntaxforgenericlambdaexpressions.“
@jbaruch http://jfrog.com/shownotes @gamussa
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<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()
.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);
@jbaruch http://jfrog.com/shownotes @gamussa
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<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()
.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);
@jbaruch http://jfrog.com/shownotes @gamussa
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<String> list = Stream.of("Spock", "Kirk", "Data", "Data", "Kirk", "Spock").sequential()
.filter(new TreeSet<>()::add).collect(Collectors.toList());System.out.println(list);
@jbaruch http://jfrog.com/shownotes @gamussa
filter(new TreeSet<>()::add) filter(i -> new TreeSet<>().add(i))!=
Newinstanceiscreatedeverytime!
Instancemethodiscreatedonce!
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException
Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException
Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");
WillneverhappenWillneverhappen
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
A. obvious / obviousB. obvious / NullPointerExceptionC. NullPointerException / obviousD. NullPointerException / NullPointerException
Optional.of("obvious").orElseGet(null);Optional.empty().map(null).orElse("obvious");
@jbaruch http://jfrog.com/shownotes @gamussa
@jbaruch http://jfrog.com/shownotes @gamussa
Identical?
@jbaruch http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
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 http://jfrog.com/shownotes @gamussa
Conclusions
@jbaruch http://jfrog.com/shownotes @gamussa
-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?
-Shownotes!-http://jfrog.com/shownotes-Slides-Video in 24 hours-Links-Ratings-Raffle! (come early)
-Did you like it?-Praise us on twitter!
-#javapuzzlersng-@gamussa-@jbaruch
-Didn’t like it?-/dev/null