Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

Youri Ackx

April 22, 2015
Tweet

More Decks by Youri Ackx

Other Decks in Technology

Transcript

  1. 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
  2. Predicates - sample That’s functional return payments.stream() .filter(p -> p.getDate()

    > date) // too late .filter(p -> p.balance == 0) // paid .collect(toList());
  3. 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
  4. 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());
  5. 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())) ) );
  6. 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())) ) ); }
  7. 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))); }
  8. 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.
  9. 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 :)
  10. 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
  11. 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
  12. 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);
  13. Remember the duck ? public interface FlyingAbility { default void

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

    { } Duck duck = new Duck(); duck.fly(); duck.swim(); Flying Swimming
  15. 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 :-(
  16. 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”); } }
  17. More serious example please public interface TraitValidityPeriod { Date startDate;

    Date endDate; default isValid(Date atDate) { ... } } public Contact implements TraitValidityPeriod { ... }
  18. 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?
  19. 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/
  20. 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
  21. “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
  22. “ 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. ”
  23. “ 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.”
  24. 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
  25. invokedynamic A bytecode instruction that facilitates the implementation of dynamic

    languages (for the JVM) through dynamic method invocation. [Java 7]
  26. 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.