28
Lambda Expressions pt1 1.1 Getting Started with Java 8 1.2 Java 8 References 1.3 Quick review of Pre-Lambda Handlers 1.4. Functional Interface Annotation 1.5 Lambda Handlers 1.6 Why Java 8? 1.7 Wra-Up Lars A. Lemos 1

Java 8 lambdas expressions

Embed Size (px)

Citation preview

Lambda Expressions pt1

1.1 Getting Started with Java 81.2 Java 8 References1.3 Quick review of Pre-Lambda Handlers1.4. Functional Interface Annotation1.5 Lambda Handlers1.6 Why Java 8?1.7 Wra-Up

Lars A. Lemos

1

1.Getting Started,Setup and Review

1.1 Getting Started with Java 81.2 Java 8 References1.3 Quick review of Pre-Lambda Handlers1.4. Functional Interface Annotation1.5 Lambda Handlers1.6 Why Java 8?1.7 Wra-Up

Lars A. Lemos

2

Lars A. Lemos 4

BooksFunctional Programming in Java - Venkat Subramanian

Java 8 Lambdas: Pragmatic Functional Programming – Richard Warburton

Java SE 8 for the Really Impatient – Cay S. Horstman

Java The Complete Reference 9th Ed – Herbert Schildt

1.2 Java 8 References

Lars A. Lemos 5

1.3 Quick review of Pre-Lambda Handlers

Anonymous inner classess Idea

You need code to respond a button click, to run in the background for threads, or to handle sorting comparisons.

Pre-lambda alternatives Separete class

• Arrays.sort(theArray, new SeparateClass(...));

Main class(which implements interface)• Arrays.sort(theArray, this);

Named inner class• Arrays.sort(theArray, new InnerClass(...));

Anonymous inner class• Arrays.sort(theArray, new Comparator<String>(){...});

Lars A. Lemos 6

1.3 Quick review of Pre-Lambda Handlers Separete classpublic class StringSorter1 {

public void doTests() {

String[] testStrings = {"one","two","three","four"};

System.out.println("Original: ");

ArrayUtils.printArray(testStrings);

Arrays.sort(testStrings, new StringLengthComparator());

System.out.println("After sorting by length: ");

ArrayUtils.printArray(testStrings);

Arrays.sort(testStrings, new LastLetterComparator());

System.out.println("After sorting by last letter: ");

ArrayUtils.printArray(testStrings);

}}

Example: StringSorter1.java Advantages• Flexible: can pass arguments to class constructor• More reusable: loosely coupled Disadavantages• Need extra stpes to call method in main app. How does handler call method in main

app?• It needs reference to the main app to do so.

Lars A. Lemos 7

1.3 Quick review of Pre-Lambda Handlers

Implementing Interface Advantages• No extra steps need to call methods in the main app.

o The code is part of the main app, so it can call any method or access any instance variable, even private ones.

• Simpleo Widely used in real life for button handlers, when you

know you will have only one button, or for threading code, when you need one method to run in the background.

Disadavantages• Inflexible: hard to have multiple different versions, since

you cannot pass argumens to the handler.o For example, if you want to sort array using two or more

ways? If you pass “this” to the second argument in Arrays.sort, it will refer to the same “compare” method both times.

o Example: StringSorter2.java

Lars A. Lemos 8

1.3 Quick review of Pre-Lambda Handlers

Named Inner Class Advantages• No extra steps need to call methods in the main app.Inner class have

full access to all methods and instances variables of surrounding class, including private ones.

o However if there is a name conflict, it is necessary to use the unpopular OuterClass.this.name syntax.

• Flexible: can define constructor and pass arguments. Disadavantageso A bit harder to understand.

Anonymous Inner Class Advantages• Full access to code of surrounding class (even private methods and

variables).• Slightly more concice than named inner class(but still bulk and

verbose). Disadavantageso Harder to understand o Not reusable(cannot use the anonymous class definition in more).

Example: StringSorter3.java

9

1.4 @FunctionalInterface Annotation

@FunctionalInterface Tells the compiler you intend this to be a functional Single Abstract Method

(SAM) interface One with exactly one abstract method Thus, for which lambdas can be used.

Check performed at compile time Also informs others developers that lambdas can be used for this interface

Analogous to @Override Does extra work at compile time, but no difference at run time (assuming it

passes the check)

Goals Simple numerical integration using rectangle (mid-point) rule Use lambdas for function to be integrated. Convenient and succinct.

Example: SimpleInterface.java , TestInterface.java

Lars A. Lemos

Lars A. Lemos 10

1.3 Lambda Handlers Desired features

Full access to code from surrounding class No confusion about meaning of “this” Much more concise, succinct, and readable Enourage a functional programming style

LambdaArrays.sort(testStrings, (s1, s2) -> s1.length() – s2.length());

What is the under the hood implementationArrays.sort(testStrings, new Comparator<String>() {

@Override

public int compare(string s1, String s2) {

s1.length() – s2.length());

}

});

Lars A. Lemos 11

1.4 Why Java 8 and Lambdas ?

Weakly (and usually dynamically ) typed JavaScript, Lisp, Scheme, etc.

Strongly typed Ruby, Scala, Clojure, etc.

Functional approach proven concise, useful, and parallelizable

Concise syntax(clear than anonymous inner classes) Convienent for new streams library

Shapes.forEach(s -> s.setColor(Color.RED)); Similar constructs used in other languages

Callbacks, closures, map/reduce idiom Step toward true functional programming

When funct. Prog approach is used, many classes of problems are easier to solve and result in code that is clearer to read and simpler to maintain.

2. Lambdas Basics

2.1 Lambdas Expressions2.2 Type Inferencing2.3 Implied Return Values2.4 Omitting Parents for One-Arg Lambdas

2.5 Effectively Final Local Variables

2.6 @FunctionalInterface Annotation 2.7 Method References

2.8 The java.util.function Package2.9 Wrap Up

Lars A. Lemos

12

13

2.1 Lambada Expressions Replace this

new SometInterface () {

@Override

public someType someMethod(args) { body; }

}

With this(args) - > { body }

ExampleArray.sort(testStrings, new Comparator<String> () ) {

@Override

public int compare(String s1, String s2) {

return (s1.length() – s2.length());

}

Array.sort(testStrings,

(String s1, String s2) - > {

return (s1.length() – s2.length() ) ; } ) ;

Example: JavaLambdas.javaLars A. Lemos

14

2.1 Lambada Expressions Part 1Basics

Old button.addActionListener (new ActionListener () {

@Override

public void actionPerformed(ActionEvent event) {

action();

}

});

Newbutton.addActionListener(event -> action());

You get an Instance of an inner class that implements interface

The expected type must be an interface that has exactly one (abstract).

It’s called “Functional Interface” or “Single Abstract Method” (SAM)

Example: ButtonFrame1.javaLars A. Lemos

15

2.2 Type Inferencing Types in argument list can usually be

omitted Since Java usually already knows the expected

parameter types for the single method of the functional interface (SAM interface)

Basic lambda(Type1 var1, Type2 var 2 …) - > { method body }

Lambda with type inference ( var1, var 2 …) - > { method body }

Lars A. Lemos

16

2.2 Type Inferencing Replace this

new SometInterface () {

@Override

public someType someMethod( T1 v1, T2 v2 ) { body; }

}

With this(v1, v2) - > { body }

Array.sort(testStrings, new Comparator<String> () ) {@Override

public int compare(String s1, String s2) {

return (s1.length() – s2.length());

}

Array.sort(testStrings,

(s1, s2) - > {

return (s1.length() – s2.length() ) ; } ) ;

Example: JavaLambdas.javaLars A. Lemos

17

2.3 Implied Return Values For body, use expression instead of block

Value of expression will be the return value, with no explicit “return” needed If method has a void return type, then automatically no return value Since lambdas are usually used only when method body is short,

this approach (using expression instead of block ) is very common.

Previous Version(var1, var2) - > { return (something); }

Lambda with expression for body(var1, var2) - > { something }

Example: JavaLambdas.java

Lars A. Lemos

18

2.4 Omitting Parents for One-Arg Lambdas

If method take single argument, parents optional

No type should be used: you must let Java infer the type. Ommiting types is normal practice

Previous Version( varName ) - > someResult()

Lambda with parentheses omittedvar - > someResult()

Example: ButtonFrame3.java

Lars A. Lemos

19

2.5 Effectively Final Local Variables Lambdas can refer to local variables that

are not declared final (but are never modified)

This is known as “effectively final” – variables where it would have been legal to declare them final.

You can still refer to mutable instance variables. “this” in a lambda refers to main class, not inner class that was

created for the lambda. There is no OuterClass.this. Also, no new level of scoping.

With explicit declarationfinal String s = “…”;

doSomething(someArg - > use(s) );

Effectively finalString s = “…”;

doSomething(someArg - > use(s) );

Example: ButtonFrame4.javaLars A. Lemos

Lars A. Lemos 20

2.6 @FunctionalInterface Annotation

MathUtilities.integrationTest(x -> x*x, 10, 100);

MathUtilities.integrationTest(x -> Math.pow(x,3), 50, 500);

MathUtilities.integrationTest(x -> Math.sin(x), 0, Math.PI);

MathUtilities.integrationTest(x -> Math.exp(x) , 2, 20);

Example: MathUtilities.java

Lars A. Lemos 21

2.7 Method References Use ClassName:: staticMethodName or

variable::instanceMethodName for lambdas Ex: Math::cos or myVar::myMethod The function must match signature of method in functional

(SAM) interface to which it is assigned.

The type is found only from the context The type of a method reference depends on what it is

assigned to. This is always true with lambdas, but more obvious here.

Ex: no predifined type for Math::cos

Lars A. Lemos 22

2.7 Method References In previous example, replace

MathUtilities.integrationTest(x-> Math.sin(x), 0, Math.PI );

MathUtilities.integrationTest(x-> Math.exp(x), 2, 20 );

With these

MathUtilities.integrationTest( Math::sin(x), 0, Math.PI );

MathUtilities.integrationTest(Math::exp(x), 2, 20 );

Type of a method reference?

Is not known until you try to assign it to a variable, in which case its type is whatever interface that variable expected. Ex: Math::sin could be different types in different contexts, but all the types would be single-method interfaces whose method could accept a single double as an argument.

Example: IntegrationTest1.java

Lars A. Lemos 23

2.8 The java.util.function Package Interfaces like Integratable widely used

So, Java 8 should build in many common cases Java.util.function defines many simple functional(SAM)

interfaces Named according to arguments and return values

Ex: replace my Integratable with builtin DoubleUnaryOperator Look in API for the method names

Althoug lambdas don’t refer to method names, your code that uses the lambdas will need to call the methods.

Type of a method reference?

Lars A. Lemos 24

2.8 The java.util.function Package Types given

Samples IntPredicate(int n, boolean out) LongUnaryOperator(long in, long out) DoubleBinaryOperator(two double in, double out)

Example DoubleBinaryOperator f = (d1, d2) -> Math.cos(d1 +

d2);

Genericized There are also generic interfaces (Function<T,R> ,

Predicate<T>) with widespread applicability. And concrete methods like “compose” and “negate”

Lars A. Lemos 25

2.8 The java.util.function Package In previous example, replace this

public static double integrate(Integratable function, ...) {

... function.eval(...);

.... With this

public static double integrate(DoubleUnaryOperator function, ...) {

... function.applyAsDouble(...);

....

}

Example: MathUtils.java

Then, omit definition of Integratable entirely Because DoubleUnaryOperator is a functional (SAM)

interface containing a method with same signature as the method of the Integratable interface.

Lars A. Lemos 26

2.8 The java.util.function Package General Case If you are tempted to create an interface purely to be

used as target for a lambda Look through java.util.function and see if one of the

functional (SAM) interfaces can be used instead.• DoubleUnaryOperator, IntUnaryOperator,

LongUnaryOperatoro double/int/long in, same type out

• DoubleBinaryOpeartor, IntBinaryOperator, LongBinaryOperatoro Two doubles/ints/longs in, same type out

• DoublePredicate, IntPredicate, LongPredicateo double/int/long in, boolean out

• DoubleConsumer, IntConsumer , LongConsumero double/int/long in, void return type

• Genericized interfaces: Function, Predicate, Consumer, etc

Lars A. Lemos 27

2.9 Wrap Up We have lambdas

Concise and succint Familiar to developers that know functional

programming Fits well with new streams API Have method references Many functional interfaces built in

Still not real functional programming Type is inner class that implements interface, not a

function Must create or find interface 1st, must know method

name. Cannot use mutable local variables

Lars A. Lemos 28

End of part I

Part II – Streams

Thank you for your patience….

[email protected] Lars Lemos toplars