it's java jim, but not as we know it!

38
© Copyright Azul Systems 2017 © Copyright Azul Systems 2015 @speakjav a azul.com It’s Java, Jim, But Not As We Know It! Simon Ritter Deputy CTO, Azul Systems 1

Upload: simon-ritter

Post on 03-Mar-2017

235 views

Category:

Software


1 download

TRANSCRIPT

Page 1: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

© Copyright Azul Systems 2015

@speakjavaazul.com

It’s Java, Jim, But Not As We Know It!

Simon RitterDeputy CTO, Azul Systems

1

Page 2: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Agenda Java Lambda expressions Lambda expression performance How far can we take lambdas? Summary

2

Page 3: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Java Lambda Expressions

Page 4: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

JDK 8 Lambda Expressions Simplified representation of behaviour in Java

– Anonymous inner class is clunky Assign to variable, pass as parameter Use wherever the type is a Functional Interface

– Much simpler than adding a function type to Java– Single abstract method– Not necessarily single method

default and static methods don’t count

4

Page 5: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambda Expression Syntax Like a method

– But not associated with a class– Typed parameters, body, return type, exceptions

Closure over values, not types– Only capture effectively-final variables

5

(parameters) -> body

Lambda operator

Page 6: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Capturing Lambdas

6

class DataProcessor { private int currentValue;

public void process() { DataSet myData = myFactory.getDataSet(); dataSet.forEach(d -> d.use(currentValue++)); }}

Page 7: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Capturing Lambdas

7

class DataProcessor { private int currentValue;

public void process() { DataSet myData = myFactory.getDataSet(); dataSet.forEach(d -> d.use(this.currentValue++));

}}

Reference to this insertedby compiler

Page 8: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Method References Method references let us reuse a method as a lambda

expression

FileFilter x = File f -> f.canRead();

FileFilter x = File::canRead;

Page 9: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Method References Format: target_reference::method_name Three kinds of method reference

– Static method– Instance method of an arbitrary type– Instance method of an existing object

9

Page 10: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Method References

10

Lambda

Method Ref

Lambda

Method Ref

Lambda

Method Ref

(args) -> ClassName.staticMethod(args)

(arg0, rest) -> arg0.instanceMethod(rest)

(args) -> expr.instanceMethod(args)

ClassName::staticMethod

ClassName::instanceMethod

expr::instanceMethod

Rules For Construction

Page 11: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Method References

(String s) -> Integer.parseInt(s);

(String s, int i) -> s.substring(i)

Axis a -> getLength(a)

Integer::parseInt

String::substring

this::getLength

Lambda

Method Ref

Lambda

Method Ref

Lambda

Method Ref

Examples

Page 12: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambda Expression Performance

Page 13: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambdas & Anonymous Inner Classes Functionally equivalent

13

myList.forEach(w -> System.out.println(w));

myList.forEach(new Consumer<String>() { @Override public void accept(String w) { System.out.println(w); }});

myList.forEach(System.out::println);

Page 14: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Anonymous Inner Classes As the name suggests, we are dealing with classes

– Compiler generates class with name like Foo$1– Type pollution

The class must be loaded at run time Instantiated like any other class Lambda expressions could be implemented this way

– Originally they were– Forces an inner class where you didn’t ask for it

You wanted a function

14

Page 15: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambda Implementation A better answer: invokedynamic

– Introduced in Java SE 7 to improve performance of dynamically typed languages running on the JVM

– Defers implementation of the Lambda to runtime Lambda compilation

– Generate invokedynamic call (lambda factory) java.lang.LambdaMetaFactory Return instance of (lambda) functional interface type

– Convert body of lambda to method Not necessary for method references

15

Page 16: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambda Implementation Non-capturing Lambda

– Simple conversion to static method in the class where the lambda is used

Capturing Lambdas– Static method with captured variables prepended as

parameters– Synthetic instance method of class using Lambda

Lambda invokes a class method

16

Page 17: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Implementation Differences Lambdas

– Linkage (CallSite)– Capture– Invocation

17

Anonymous inner classes– Class loading– Instantiation– Invocation

Non-capturing lambdas automatically optimise Method references are slightly more optimal -XX:+TieredCompilation gives better Lambda

results– Advice is don’t use -XX:-TieredCompilation

Page 18: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

How Far Can We Take Lambdas?

With inspiration from Jarek Ratajski

Page 19: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017 19

Alonso Church

The λ Calculus (1936)

What does this have to do with Java?

Page 20: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Exploding Head Lambdas Java programmers are typically imperative programmers Functional programming is not imperative

– As we’ll see Lambda Calculus and Turing Machines are equivalent But will give you a headache

– At least it did me! What can we do only using Lambda expressions?

– And one functional interface

20

Page 21: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Functional Interface

@FunctionalInterfacepublic interface Lambda { Lambda apply(Lambda lambda);}

Page 22: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Function Basics Identity [ λx.x ]

Lambda identity = x -> x;

Lambda identity = new Lambda { Lambda apply(Lambda x) { return x; }};

Page 23: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Function Basics (Booleans) Boolean false [ λf.λx.x ]

boolFalse = f -> (x -> x); // Always returns identity

boolFalse = new Lambda { Lambda apply(Lambda f) { return new Lambda { Lambda apply(Lambda x) { return x; } }}};

Page 24: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Function Basics (Booleans) Boolean true [ λf.λx.f ]

boolTrue = f -> (x -> f); // Never returns identity

boolTrue = new Lambda { Lambda apply(Lambda f) { return new Lambda { Lambda apply(Lambda x) { return f; } }}};

Page 25: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Church Numerals Zero [ λf.λx.x ]

• Identity for addition and subtraction (a ± 0 = a)• The Lambda is the same as false• The function is applied zero times to the argument

zero = f -> x -> x; One [ λf.λx.(f x) ] one = f -> x -> f.apply(x);

Two [ λf.λx.(f (f x)) ] two = f -> x -> f.apply(f.apply(x));

25

Page 26: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Church Encoding Successor: n++ [ λn.λf.λx.f(n f x) ] successor = n -> f -> x -> f.apply(n.apply(f).apply(x));

26

Page 27: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Church Encoding Predecessor: n--

27

predecessor = n -> f -> x -> n.apply(g -> h -> h.apply(g.apply(f))) .apply(u -> x).apply(u -> u);

[ λn.λf.λx.n(λg.λh.h(g f))(λu.x)(λu.u) ]

Page 28: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Church Encoding Add: m + n [ λm.λn.λf.λx ((m f) ((n f) x)) ] m -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))

Subtract: m - n [ λm.λn.(n predecessor) m ] m -> n -> m.apply(predecessor).apply(n)

28

Page 29: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdas

Lambda two = f -> x -> f.apply(f.apply(x));

Lambda plus = m -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x));

Lambda four = plus.apply(two).apply(two);

4 = + 2 2 (Polish notation)

Page 30: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdasm -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))

n -> f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(n.apply(f).apply(x))

Page 31: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdasm -> n -> f -> x -> m.apply(f).apply(n.apply(f).apply(x))

n -> f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(n.apply(f).apply(x))

f -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x).apply(f).apply(x))

Page 32: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdasf -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))

Page 33: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdasf -> x -> f -> x -> f.apply(f.apply(x)).apply(f) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(f -> x -> f.apply(f.apply(x)).apply(f).apply(x))f -> x -> x -> f.apply(f.apply(x)) .apply(x -> f.apply(f.apply(x)).apply(x))

Page 34: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Solving 2 + 2 With Lambdasf -> x -> x -> f.apply(f.apply(x)) .apply(x -> f.apply(f.apply(x)).apply(x))

f -> x -> x -> f.apply(f.apply(x)) .apply(f.apply(f.apply(x)))

f -> x -> x -> f.apply(f.apply(x)) .apply(f.apply(f.apply(x)))

f -> x -> f.apply(f.apply(f.apply(f.apply(x)))= 4!

Page 35: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Summary

Page 36: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

Lambda Expressions Very useful and powerful

– Succinct way to parameterise behaviour Better performance than anonymous inner class

– Invokedynamic implementation Can be used in weird and wonderful ways

– Not necessarily to be recommended!

36

Page 37: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

More Information Dixin Yan’s blog

– weblogs.asp.net/dixin (C# based, but useful)– October 2016

Jarek’s presentation from Voxxed Zurich– https://www.youtube.com/watch?v=Dun8ewSeX6c

37

Page 38: It's Java Jim, But Not As We Know It!

© Copyright Azul Systems 2017

© Copyright Azul Systems 2015

@speakjavaazul.com

It’s Java, Jim, But Not As We Know It!

Simon RitterDeputy CTO, Azul Systems

38