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

Java 8 - Love & Hate

Java 8 - Love & Hate

Introduction to new Java 8 features

Duarte Duarte

December 20, 2013
Tweet

More Decks by Duarte Duarte

Other Decks in Programming

Transcript

  1. Java 8 Love & Hate By Duarte Duarte, Eduardo Martins,

    Miguel Marques and Ruben Cordeiro ESOF/MIEIC/FEUP - 2013/2014
  2. Timeline JDK 1.0 (January, 1996) JDK 1.1 (February, 1997) J2SE

    1.2 (December, 1998) J2SE 1.3 (May, 2000) J2SE 1.4 (February, 2002) J2SE 5.0 (September, 2004) Java SE 6 (December, 2006) Java SE 7 (July, 2011) Java SE 8 (March, 2014) [scheduled]
  3. Lambdas (int x, int y) ‐> x + y ()

    ‐> 42 (String s) ‐> { System.out.println(s); }
  4. Lambdas Examples Before JButton btn = new JButton(); final PrintStream

    pStream = ...; btn.addActionListener(new ActionListener { @Override public void actionPerformed(ActionEvent e) { pStream.println("Button Clicked!"); } }); After JButton btn = new JButton(); final PrintStream pStream = ...; btn.addActionListener(e ‐> pStream.println("Button Clicked!"));
  5. Lambdas Examples ArrayList<String> strs = ...; Collections.sort(strs, (s1, s2) ‐>

    s2.length() ‐ s1.length()); new Thread(() ‐> { connectToService(); sendNotification(); }).start();
  6. Functional Interfaces Example @FunctionalInterface public interface Runnable { public abstract

    void run(); } Runnable r = () ‐> System.out.println("Hello World!");
  7. java.util.function Predicate<T> - a boolean-valued property of an object Consumer<T>

    - an action to be performed on an object Function<T, R> - a function transforming a T to a R Supplier<T> - provide an instance of a T (such as a factory) UnaryOperator<T> - a function from T to T BinaryOperator<T> - a function from (T, T) to T
  8. Method References Examples class Person { private String _name; private

    int _age; public int getAge() { return _age; } public String getName() { return _name; } } Person[] people = ...; Comparator<Person> byName = Comparator.comparing(Person::getName); Arrays.sort(people, byName);
  9. Method References Kinds of method references A static method (ClassName::methName)

    An instance method of a particular object (instanceRef::methName) A super method of a particular object (super::methName) An instance method of an arbitrary object of a particular type (ClassName::methName) A class constructor reference (ClassName::new) An array constructor reference (TypeName[]::new)
  10. Method References More Examples Consumer<Integer> b1 = System::exit; Consumer<String[]> b2

    = Arrays::sort; Consumer<String> b3 = MyProgram::main; Runnable r = MyProgram::main;
  11. Why default methods? Suppose Java 8 is out and has

    lambdas. We want to start using them: List<?> list = ... list.forEach(...); // lambda code goes here
  12. There's a problem The forEach method isn’t declared by java.util.list

    nor the java.util.collection interface yet. Adding extra methods to the java.util.collection interfaces would break the existing implementations.
  13. Default Methods We have lambdas, but we can't force new

    behaviours into the current libraries. Solution: default methods.
  14. Default Methods Default methods or defender methods, can now be

    added to interfaces providing a default implementation of the declared behavior.
  15. public interface A { default void foo(){ System.out.println("Calling A.foo()"); }

    } public interface B { default void foo(){ System.out.println("Calling B.foo()"); } } public class Clazz implements A, B { } Does this code compile?
  16. Option A: public class Clazz implements A, B { public

    void foo(){} } We resolve it manually by overriding the conflicting method. Option B: public class Clazz implements A, B { public void foo(){ A.super.foo(); // or B.super.foo() } } We call the default implementation of method foo() from either interface A or B instead of implementing our own.
  17. Going back to the example of forEach method, how can

    we force it's default implementation all the iterable collections?
  18. Let's take a look at the Java UML for all

    the iterable Collections: In order to add a default behaviour to all the iterable collections, a default forEach method was added to the Iterable<E> interface.
  19. We can find its default implementation in java.lang.iterable interface: @FunctionalInterface

    public interface Iterable { Iterator iterator(); default void forEach(Consumer<? super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } }
  20. The forEach method takes java.util.function.Consumer functional interface type as a

    parameter which enables us to pass in a lambda or a method reference as follows: List<?> list = ... list.forEach(System.out::println); However, this is also valid for object of class Set<E> or Queue<E> for example, since both classes implement the Iterable interface.
  21. Summary Default methods can be seen as a bridge between

    lambdas and JDK libraries. However, the scope of this feature surpasses the retrocompatibility domain: they can also help reduce the amount of redudant code when dealing with libraries like Swing.
  22. Accumulators The continual evolution of uses of concurrency and parallelism

    in applications requires continual evolution in library support. For this purpose, the Accumulators were introduced.
  23. Accumulators Maintaining a single count, sum, etc., that is updated

    by possibly many threads is a common scalability problem. A set of new classes were created for that purpose: DoubleAccumulator DoubleAdder LongAccumulator LongAdder
  24. Accumulators Package java.util.concurrent mechanisms synchronized operations between threads, however if

    all you want to do is increment a variable across threads, it was overkill and then some. These classes are usually preferable to alternatives when multiple threads update a common value that is used for purposes such as summary statistics that are frequently updated but less frequently read.
  25. Accumulators Both the DoubleAdder and LongAdder classes can be seen

    as specific subsets of the DoubleAccumulator and LongAccumulator functionality. The call new DoubleAdder() is equivalent to new DoubleAccumulator((x, y) ‐> x + y, 0.0). The call new LongAdder() is equivalent to new LongAccumulator((x, y) ‐> x + y, 0L).
  26. DoubleAccumulator da = new DoubleAccumulator((x,y) ‐> x + y, 0.0);

    List<Double> doubles = Arrays.asList(1.0, 2.0, 3.0, 4.0, 10.0); doubles.forEach(da::accumulate); System.out.println("Result: " + da.doubleValue()); Output: Result: 24
  27. LongAdder la = new LongAdder(); List<long> longs = Arrays.asList(10, 20,

    30, 40, 100); longs.forEach(la::accumulate); System.out.println("Result: " + la.longValue()); Output: Result: 200
  28. java.util.stream ArrayList<Student> students = …; Stream stream = students.stream(); //

    sequential version // parallel version Stream parallelStream = students.parallelStream(); traversed once infinite lazy
  29. java.util.stream Stream sources collections LinkedHashSet set; Stream stream = set.stream();

    generators Random random = new Random(); Stream randomNumbers = Stream.generate(random::nextInt); from other streams Stream newStream = Stream.concat(stream, randomNumbers);
  30. java.util.stream Intermediate operations .filter - excludes all elements that don’t

    match a Predicate .map - perform transformation of elements using a Function .flatMap - transform each element into zero or more elements by way of another Stream .peek - performs some action on each element .distinct - excludes all duplicate elements (equals()) .sorted - orderered elements (Comparator) .limit - maximum number of elements .substream - range (by index) of elements List persons = ...; Stream tenPersonsOver18 = persons.stream() .filter(p ‐> p.getAge() > 18) .limit(10);
  31. java.util.stream Terminating operations 1. Obtain a stream from some sources

    2. Perform one or more intermidate operations 3. Perform one terminal operation reducers like reduce(), count(), findAny(), findFirst() collectors (collect()) forEach iterators List<Person> persons = ..; List<Student> students = persons.stream() .filter(p ‐> p.getAge() > 18) .map(Student::new) .collect(Collectors.toList());
  32. java.util.stream Parallel & sequential List<Person> persons = ..; List<Student> students

    = persons.stream() .parallel() .filter(p ‐> p.getAge() > 18) .sequential() .map(Student::new) .collect(Collectors.toCollection(ArrayList::new));
  33. java.time Time Zones ZoneId zone = ZoneId.systemDefault(); ZoneId zoneBerlin =

    ZoneId.of("Europe/Berlin"); Clock clock = Clock.system(zoneBerlin);
  34. java.time Human Readable Time class LocalDate { public static LocalDate

    now() { ... } public static LocalDate now(ZoneId zone) { ... } public static LocalDate now(Clock clock) { ... } } LocalDate date = LocalDate.now(); System.out.printf("%s‐%s‐%s", date.getYear(), date.getMonthValue(), date.getDayOfMonth());