Youri Ackx
April 22, 2015
150

# Java 8 - Migration follow-up

A follow-up talk after we moved from Java 6 to Java 8. Code snippets, practical use, default methods as traits, performance...

April 22, 2015

## Transcript

Ackx

3. ### Sum BigDecimal availAmount = regul.findOperations().stream() .map(r -> r.getAmount().getTotal()) .reduce(BigDecimal.ZERO, BigDecimal::add);

Groovy : def amountsStr = ["10.00", "15.50", "20.25"] def amounts = amountsStr.collect { it as BigDecimal } def sum = amounts.sum() assert sum == 45.75 as BigDecimal assert sum.getClass() == BigDecimal.class

5. ### Predicates - sample That’s functional return payments.stream() .filter(p -> p.getDate()

> date) // too late .filter(p -> p.balance == 0) // paid .collect(toList());
6. ### Predicates - sample That’s better Predicate<Payment> tooLate = p ->

p.getDate() > date; Predicate<Payment> paid = p -> p.balance == 0; return payments.stream() .filter(tooLate) .filter(paid) .collect(toList()); • Clearly expresses your intention • Details are irrelevant • Better for real-life multi-line filters
7. ### Predicates - .or() return payments.stream() .filter(p -> p.getDate() > date

|| p.balance == 0) .collect(toList()); vs return payments.stream() .filter(tooLate.or(paid)) .collect(toList());

10. ### Predicates private boolean anyMatch(List<DateInterval> intervals, Date startDate, Date endDate) {

return intervals.stream().anyMatch(di -> ( (startDate == null && di.getStartDate() == null) || (startDate != null && startDate.equals(di.getStartDate())) ) && ( (endDate == null && di.getEndDate() == null) || (endDate !=null && endDate.equals(di.getEndDate())) ) );
11. ### Predicates private boolean anyMatch(List<DateInterval> intervals, Date startDate, Date endDate) {

return intervals.stream().anyMatch(di -> ( (startDate == null && di.getStartDate() == null) || (startDate != null && startDate.equals(di.getStartDate())) ) && ( (endDate == null && di.getEndDate() == null) || (endDate !=null && endDate.equals(di.getEndDate())) ) ); }
12. ### Predicates private boolean anyMatch(List<DateInterval> intervals, Date startDate, Date endDate) {

Predicate<DateInterval> startsBothNull = di -> startDate == null && di.getStartDate() == null; Predicate<DateInterval> startsMatch = di -> startDate != null && startDate.equals(di.getStartDate()); Predicate<DateInterval> endsBothNull = di -> endDate == null && di.getEndDate() == null; Predicate<DateInterval> endsMatch = di -> endDate!= null && endDate.equals(di.getEndDate()); return intervals.stream().anyMatch( (startsBothNull.or(startsMatch)).and(endsBothNull.or(endsMatch))); }

14. ### Method reference IJ 14 triggers a warning → Follow the

idioms (even if you use Eclipse)
15. ### Do it in style List<Foo> foos = bars.stream() .filter(...) .map(...)

.collect(toList()); Also OK to inline the whole expression if short. Please avoid horizontal scrolling… Or buy me a 30” HD screen.
16. ### Do it in style Map<String, FooBar> stuff = new HashMap<String,

FooBar>(); Since Java 7 : Map<String, FooBar> stuff = new HashMap<>(); If your IDE does not automatically gives you the short form, ask for a refund and consider buying an IDEA license :)
17. ### Do it in style (not Java specific) Keep in clean

– Broken window theory Things like : • Javadoc warnings : missing param, incorrect param… • Possible NPE inspection • Unused variable • Initial assignment non necessary
18. ### Do it in style (not Java specific) Let your IDE

yell, then fix all mistakes Toolchains like node.js + grunt + lint won’t even let you build

21. ### Cast and filter elements in a collection List<Cotisation> cotisations =

entitesComptables.stream() .filter(ec -> ec instanceof Cotisation) .map(Cotisation.class::cast) .collect(Collectors.toList()); vs Google Collections Iterable<Cotisation> cotisations = filter(entiteComptables, Cotisation.class);

23. ### Dates our.DateUtil Calendar our.Calendars java.util.Date java.time.* ‒ and now we

have one extra set of problems

25. ### Remember the duck ? public interface FlyingAbility { default void

fly() { System.out.println(“Flying”); } } public interface SwimmingAbility { default void swim() { System.out.println(“Swimming”); } }
26. ### Remember the duck ? public class Duck implements FlyingAbility, SwimmingAbility

{ } Duck duck = new Duck(); duck.fly(); duck.swim(); Flying Swimming
27. ### Scala ducks and fishes and birds val duck = new

Animal with FlyingAbility with SwimmingAbility; val fish = new Animal with SwimmingAbility; val bird = new Animal with FlyingAbility; Not in Java 8 :-(
28. ### More serious example please public interface Loggable { default Logger

logger() { return LoggerFactory.getLogger(this.getClass()); } } public SomeAction implements Loggable { public void something() { logger().debug(“Doing something”); } }
29. ### More serious example please public interface TraitValidityPeriod { Date startDate;

Date endDate; default isValid(Date atDate) { ... } } public Contact implements TraitValidityPeriod { ... }

31. ### Wait a minute... Default methods were introduced for backward compatibility

reasons. Is it wise to use them as a poor’s man version of traits?

33. ### Let’s argue here When I hear... … I reply It

was not intended for that purpose That does not mean you can’t do something great out of it Things can get ugly if you abuse the feature So let’s not abuse it -- see examples above Things can get out of hands with complex hierarchy (diamond problem) So let’s just avoid that Tricking default methods into stateful mixins is bad Of course, keep it stateless
34. None
35. ### “Your word is a lamp to my feet and a

light to my path” Psalm 119:115 http://stackoverflow.com/questions/28681737/java-8-default-methods-as-traits-safe

37. ### “ The proximate reason for adding default methods to interfaces

was to support interface evolution, but we were well aware that we were going beyond that. Whether you consider that to be "interface evolution++" or "traits--" is a matter of personal interpretation. ”
38. ### “ so long as you stick to what the mechanism

actually supports, rather than trying to wishfully stretch it to something it does not support, you should be fine.”

40. ### I wouldn’t worry about it* *In most cases, on our

current project
41. ### InfoQ - Java 8 Lambdas - A Peek Under the

Hood “ (...) to get the best out of lambda expressions it is important to use them idiomatically. If lambda expressions are used to represent small, pure functions there is little need for them to capture anything from their surrounding scope. As with most things - if you keep it simple things perform well. ” Warburton, Urma & Fusco
42. ### invokedynamic A bytecode instruction that facilitates the implementation of dynamic

languages (for the JVM) through dynamic method invocation. [Java 7]