Pro Yearly is on sale from $80 to $50! »

Java 8 - Migration follow-up

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

6acd3df818349485f3942b5c6d16247a?s=128

Youri Ackx

April 22, 2015
Tweet

Transcript

  1. Java 8 The road to enlightenment @ UCM ;-) Youri

    Ackx
  2. As seen in your code Insert some real-life examples here

  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
  4. Predicates Practical use cases

  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());
  8. Predicates - .negate() return payments.stream() .filter(paid) .filter(tooLate.negate()) .collect(toList());

  9. Predicates - .orElse() return payments.stream .sorted() .findFirst() .orElse(null);

  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))); }
  13. Misc

  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
  19. Pain Points

  20. Debugging :-(

  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);
  22. Dates

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

    have one extra set of problems
  24. Traits

  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 { ... }
  30. More serious example please TraitPeriodeValidite TraitPeriodeDao TraitIdentiteAction ?

  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?
  32. This is guy says no “ How your addiction to

    Java 8 default methods may make pandas sad and and your teammates angry ” Oleg Shelajev http://zeroturnaround.com/rebellabs/how-your-addiction-to-java-8-default-methods-may-make-pandas-sad-and-your-teammates-angry/
  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
  36. “ it's safe if you use them safely :) ”

  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.”
  39. Performance

  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]
  43. JDK 8: Lambda Performance study Sergey Kuksenko http://www.oracle.com/technetwork/java/jvmls2013kuksen-2014088.pdf Gory details

  44. Youri Ackx Agile and Pragmatic Java/Grails Developer @YouriAckx

  45. Attributions See references on specific slides Java 8 Follow Up

    by Youri Ackx is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.