Download - Java 8 - project lambda

Transcript
Page 1: Java 8 - project lambda

Java 8 :: Project Lambda

λIvar Conradi Østhus

[email protected]

1 / 31

Page 2: Java 8 - project lambda

Java 8 - a few new (important) featuresLambda expressions

greater impact than generics in Java 1.5Stream APIDefault methods in interfacesCompact ProfilesNashorn JavaScript EngineMore annotationsParallel Array Sorting(new) Date & Time APIConcurrency Updates...Scheduled for March 2014

Complete list: http://openjdk.java.net/projects/jdk8/features

2 / 31

Page 3: Java 8 - project lambda

Warning:

a lot of code examples in this presentation!

3 / 31

Page 4: Java 8 - project lambda

Imperative style: for each element

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

//1: old loopfor(int i = 0; i < numbers.size(); i++) { System.out.println(i);}

//2: enhanced for-loopfor(Integer n : numbers) { System.out.println(n);}

4 / 31

Page 5: Java 8 - project lambda

Declarative style: for each element

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

public interface Iterable<T> { ... void forEach(Consumer<? super T> action); ...}

With anonymous inner class:

numbers.forEach(new Consumer<Integer>() { public void accept(Integer number) { System.out.println(number); }});

With lambda expression:

numbers.forEach((Integer n) -> System.out.println(n));

5 / 31

Page 6: Java 8 - project lambda

What is a functional interfaces?

@FunctionalInterfacepublic interface Predicate<T> { boolean test(T t);}

one abstract unimplemented methodoptional @FunctionalInterface annotationalready a lot of functional interfaces in javaJava API will be full of functional interfaces

6 / 31

Page 7: Java 8 - project lambda

Functional interfaces added in Java 8

Consumer<T> //takes an input T and performs an operation on it.

Supplier<T> //a kind of factory, will return a new or existing instance.

Predicate<T>//Checks if argument T satisfies a requirement.

Function<T, R> //Transform an argument from type T to type R.

7 / 31

Page 8: Java 8 - project lambda

Methods taking a functional interface will accept:

an anonymous inner classa lambda expressiona method reference

8 / 31

Page 9: Java 8 - project lambda

Lambda: typesSingle expression

(Integer i) -> i * 2;

Statement block

(int x, int y) -> { return x + y; }

//multiple lines of code(int n) -> { int value = n*2; return value;};

9 / 31

Page 10: Java 8 - project lambda

Lambda: type inference

(Integer i) -> i * 2;

(i) -> i * 2;

i -> i*2;

//Multiple params(int x, int y) -> x + y

(x, y) -> x + y

10 / 31

Page 11: Java 8 - project lambda

Reuse lambdas

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

Function

public static Consumer<Integer> consumer() { return (Integer n) -> System.out.println(n);}

numbers.forEach(consumer());

Variable

public Consumer<Integer> consumer = (Integer n) -> System.out.println(n);

numbers.forEach(consumer);

11 / 31

Page 12: Java 8 - project lambda

Method reference

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

//Lambdanumbers.forEach(n -> System.out.println(n));

//Method referencenumbers.forEach(System.out::println);

12 / 31

Page 13: Java 8 - project lambda

Lambda summary

(int x, int y) -> { return x + y; }

(x, y) -> x + y

x -> x + x

() -> x

enables better librariesuses lexical scopingrequires effectively final

13 / 31

Page 14: Java 8 - project lambda

The Java Stream API

14 / 31

Page 15: Java 8 - project lambda

Task: Double and sum all even numbers

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

Imperative solution

int sumOfDoubledEvenNbrs = 0;for(int number : numbers) { if(number % 2 == 0) { sumOfDoubledEvenNbrs += number * 2; }}

Declarative solution

int sum = numbers.stream() .filter(n -> n % 2 == 0) .mapToInt(n -> n * 2) .sum();

15 / 31

Page 16: Java 8 - project lambda

The Java Stream APIIntegration of lambda expressions with the Collection API'sAn abstraction for specifying aggregate computation on data setStreams are like iterators, yield elements for processingStreams can be finite and infiniteIntention: replace loops for aggregate operations

Streams gives us:

more readable codemore composable operationsparallizable

Think of Stream pipelines as builders:

have stream sourceadd many intermediate operationsexecute pipeline ONCE

Side note: Pipes in linux

cat index.html | tr "[A-Z]" "[a-z]" | grep lambda | sort

16 / 31

Page 17: Java 8 - project lambda

Source

collections, arrays, generator functions, IOcan be finite or infinitedo NOT modify the source during query

Intermediate operations

filter, map, mapToInt, flatMap, sorted, distinct, limit...stateless or statefulllazy -- returns new streamslambdas used to transform or drop values

Terminal operation

Aggregation: toArray, toList, reduce, sum, min, max, count, anyMatch, allMatchIteration: forEachSearching: findFirst, findAnyproduces a result / side-effect

17 / 31

Page 18: Java 8 - project lambda

Stream: sourcesCollections

List<Person> persons = new ArrayList<>();

Stream<Person> personStream = persons.stream();

IO

Stream<String> lineStream = bufferedReader.lines();

Stream factories

//rangeIntStream numbers = IntStream.range(0, 10);

//random numbersDoubleStream randomDoubles = new Random().doubles();

IntStream randomInts = new Random().ints(0, 10);

(Primitive streams are included for performance reasons)

18 / 31

Page 19: Java 8 - project lambda

Stream: intermediate operationsreturns a Stream, not elementsthey are lazy

filter

Stream<Person> stream = persons.stream().filter(p -> p.getAge() > 17);

map

Stream<String> stream = persons.stream().map(Person::getName);

mapToInt

IntStream stream3 = persons.stream().mapToInt(Person::getAge);

19 / 31

Page 20: Java 8 - project lambda

Stream: statefull intermediate operationsharder to parallelizeExamples: limit, substream, sorted, distinct

Stream<Person> sortedStream = persons.stream() .filter(p -> p.getAge() > 17) .sorted((p1, p2) -> p1.getAge() - p2.getAge());

20 / 31

Page 21: Java 8 - project lambda

Stream: terminal operationsreturn non-stream elementseager: force evaluation of the stream

Task: Find the average age in Sandnes

OptionalDouble average = persons.stream() .filter(p -> p.getCity().equals("Sandnes")) .mapToInt(p -> p.getAge()) .average();

(How would an imperative solution look like?)

21 / 31

Page 22: Java 8 - project lambda

Imperative solutionTask: Find the average age in Sandnes

int sum = 0;int count = 0;for(Person person : persons){ if(person.getCity().equals("Sandnes")) { sum += person.getAge(); count ++; }}double averageAgeInSandnes = (double)sum / count;

The Stream solution:

OptionalDouble average = persons.stream() .filter(p -> p.getCity().equals("Sandnes")) .mapToInt(p -> p.getAge()) .average();

22 / 31

Page 23: Java 8 - project lambda

Stream: Collectoraggregate values in to a containermany predefined collectors in java.util.stream.Collectors

countingaveraging/summarizing/sum/mintoList/toMap/toSetreducinggroupingBymapping

Collectors.toSet()

Set<String> names = persons.stream() .map(Person::getName) .collect(toSet());

Result:

[Ivar Østhus, Donald Duck, Ola Hansen, Kari Normann, Silje Hansen, Knerten Lillebror]

23 / 31

Page 24: Java 8 - project lambda

Stream: Collector - groupingByCollectors.groupingBy: age

Map<Integer, List<Person>> personsByAge = persons.stream().collect(groupingBy(Person::getAge));

groupingBy age, and only get their names

Map<Integer, List<String>> nameByAge = persons.stream() .collect(groupingBy(Person::getAge, mapping(Person::getName, toList())));

24 / 31

Page 25: Java 8 - project lambda

Stream the contents of a CSV fileMap persons in a CSV to a list of persons and return the 50 first adults.

name, age, city, countryIvar Østhus, 28, Oslo, NorwayViswanathan Anand, 43, Mayiladuthurai, IndiaMagnus Carlsen, 22, Tønsberg, Norway..

InputStream is = new FileInputStream(new File("persons.csv"));BufferedReader br = new BufferedReader(new InputStreamReader(is));

List<Person> persons = br.lines() .substream(1) .map(toPerson) .filter(isAdult) .limit(50) .collect(toList());

//lambdaspublic static Function<String, Person> toPerson = (line) -> { String[] p = line.split(", "); return new Person(p[0], Integer.parseInt(p[1]), p[2], p[3]);};public static Predicate<Person> isAdult = p -> p.getAge() > 17;

25 / 31

Page 26: Java 8 - project lambda

Parallel Streams

//SequentialOptionalDouble average = persons.stream() .filter(p -> p.getCity().equals("Sandnes")) .mapToInt(p -> p.getAge()) .average();

//ParallelOptionalDouble average = persons.parallelStream() .filter(p -> p.getCity().equals("Sandnes")) .mapToInt(p -> p.getAge()) .average();

26 / 31

Page 27: Java 8 - project lambda

Parallel Streams: visual model

(Source: https://oracleus.activeevents.com/2013/connect/sessionDetail.ww?SESSION_ID=7942)

27 / 31

Page 28: Java 8 - project lambda

Streams: performance

N = size of sourceQ = cost per-element through the pipelineN * Q ~= cost of pipeline

Larger N * Q → higher chance of good parallel performanceGenererally it is easier to know NFor small data sets → sequential usually winsComplex pipelines are harder to reason aboutWhat are the stream characteristics?Do not assume parallel is always faster!

MEASURE!!!

28 / 31

Page 29: Java 8 - project lambda

Interface: default methodsJava Collections Framework

designed fifteen years agowithout a functional orientationdo not have a method forEach, stream, ..

Until now adding new methods to an interface has been impossible without forcingmodification to existing classes

Solution: default methods in interfaces(also called virtual extension methods or defender methods)

A clever way to enhance existing interfaces with new methods

interface Iterator { // existing method declarations default void skip() { if (hasNext()) next(); }}

29 / 31

Page 30: Java 8 - project lambda

Stream API: summarySources:

Collections, Generator functions, IO

Intermediate functions:filter, map, sorted, limitlazy

Terminal operations:sum, max, min, collect, groupingByeager

30 / 31

Page 31: Java 8 - project lambda

Books:

Functional Programming in Java Vankat Subramaniam

Java 8 Lambdas in Action Raoul-Gabriel Urma, Mario Fusco, and AlanMycroft

Presentations:

https://oracleus.activeevents.com/2013/connect/sessionDetail.ww?SESSION_ID=7942https://oracleus.activeevents.com/2013/connect/sessionDetail.ww?SESSION_ID=7504http://www.slideshare.net/jaxlondon2012/lambda-a-peek-under-the-hood-brian-goetz

Videos:

http://parleys.com/channel/5243df06e4b0d1fb3c78fe31/presentations?sort=date&state=public

31 / 31