Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
124 views

Lambda Expressions in Java 8: Reading Material

This document provides an overview of lambda expressions in Java 8. It defines what a lambda expression is, explains functional interfaces, and motivates the use of lambda expressions over anonymous classes. It covers lambda expression syntax, variable scoping in closures, exceptions, method references, and constructor references. Reading materials with more details on lambda expressions in Java are referenced.

Uploaded by

Vikram Jha
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
124 views

Lambda Expressions in Java 8: Reading Material

This document provides an overview of lambda expressions in Java 8. It defines what a lambda expression is, explains functional interfaces, and motivates the use of lambda expressions over anonymous classes. It covers lambda expression syntax, variable scoping in closures, exceptions, method references, and constructor references. Reading materials with more details on lambda expressions in Java are referenced.

Uploaded by

Vikram Jha
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

Lambda Expressions in Java 8

COP 4331/5339 – OODP/OOSD

Instructor: Dr. Ionut Cardei

Reading material:

Lambda Expressions in Java 8, by Cay Horstmann (Dr.
Dobbs): http://www.drdobbs.com/jvm/lambda-expressions-in-java-8/240166764

Java Tutorial:
https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html

Lambda Quick Start:
http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html


Lambda Expressions in Java, by Angelika Langer & Klaus Kreft
http://www.angelikalanger.com/Lambdas/Lambdas.pdf
Overview

What is a λ-expression ?

Functional Interfaces

Motivation for Lambdas

Lambda Expression for Comparator

Lambda Expression Syntax

Closures and Variable Access

Dealing with Exceptions

Method References

Constructor References

Further Reading
What is a λ-expression ?

A block of code with parameters, i.e. a function with
no name that can access effectively final variables
from the surrounding scope (lexically scoped)

Captures free variables, instance and class
variables from the enclosing scope

Implemented with a closure.

Lambdas can be stored, referenced by variables
and passed around for execution at a later time
What is a λ-expression ?

It can be used anywhere where an object
implementing a functional interface is
expected

Other languages supporting lambdas:
 JavaScript, C++, Python, Scala, LISP, Scheme,
Haskell, Matlab, F#, Perl, Lua, PHP, Ruby, TCL
 Introduced by functional languages

Java is very late to this party
Functional Interfaces

A Java interface with only one abstract (i.e. unimplemented)
method declared in its definition

Optional Java annotation: @FunctionalInterface

Examples:

public interface Comparable<T> { public interface Comparator<T> {


int compareTo(T other); int compare(T p1, T p2);
} }

@FunctionalInterface public interface Runnable


public interface ActionListener {
{ void run();
int actionPerformed(ActionEvent event); }
}
Motivation for Lambdas

Using named or anonymous classes for instances of
functional interfaces is verbose

The compiler can infer parameter and return types from
actual parameters.
anonymous class

Collections.sort(countries,
new Comparator<Country>() parameter types
{
public int compare(Country country1, Country country2)
{
return country1.getName().compareTo(country2.getName());
}
} );

function definition
useful expression
Motivation for Lambdas
Sorting with anonymous class object: anonymous class

Collections.sort(countries,
new Comparator<Country>() parameter types
{
public int compare(Country country1, Country country2)
{
return country1.getName().compareTo(country2.getName());
}
});

function definition
useful expression

Same thing, with a lambda expression:


Only the function definition is needed
Collections.sort(countries,
(country1, country2) ->
country1.getName().compareTo(country2.getName());
);
Motivation for Lambdas

Less typing, more convenient

More readable code

Support for a stream abstraction where objects are processes in a
pipeline mode (and not related to the java.io I/O classes).

Support for lazy evaluation and optimization
– delayed object creation, on demand
– implicit parallelization of code, convenient for programmers,
with parallel streams

Support for Fluent Programming, i.e. chaining an operation that
returns a value followed by an operation that uses that value and
returns a new value, and so on.
Lambda Expression for Comparator

Same example, now with a lambda-expression (in blue color):

Collections.sort(countries,
(Country country1, Country country2) ->
country1.getName().compareTo(country2.getName());
);


If the compiler can infer parameter types, we can omit
them:
Collections.sort(countries,
(country1, country2) ->
country1.getName().compareTo(country2.getName());
);
Lambda Expression Syntax

For a code block of one statement:
(paramlist) -> expression

For a code block of multiple statements:
(paramlist) -> {
statement1; …....
statementn;
}
 If the lambda returns a statement: use return expr;

 (paramlist) is (Type1 p1, … , Typen pn)



If the parameter list has just one parameter with inferred type,
you can omit the parentheses

No need to specify return type
Lambda Expression with Multiple
Statements

A Comparator<String> comparing string lengths
Collections.sort(stringlist,
(String s1, String s2) -> {
if (s1.length() < s2.length()) return -1;
if (s1.length() > s2.length()) return +1;
return 0;
} );

An ActionListener (from Chapter 4):
helloButton.addListener(
event -> { // or (event) or (ActionEvent event)
String s = jText1.getText();
System.out.println(“the text was “ + s);
jText1.setText(“Hello World”);
} );
Parameterless Lambdas

Simply write () as the parameter list:

Example that creates a new thread from a
Runnable object and starts the thread:
new Thread(
( ) -> { // Runnable has method void run()
System.out.println(“runs in another thread”);
}
).start();

(in this one line function example the { and } are optional.
I wrote them because of the comment.)
Closures and Variable Access

A closure is a function together with its environment:
– actual parameters, instance and class variables from
the enclosing class
– ... plus local variables that are effectively final (called
free variables)

for (int i=0; i<n; i++) {


final int index = i; // a final variable
Date now = new Date(); // an effectively final variable

new Thread(
( ) -> {
System.out.println(“thread started, index “ + index + “ at
time “ + now);
}
);
} // for i=...
Closures and Variable Access

Lexical scope: the lambda expression is not a scope
of it own, but it is part of the enclosing scope

“this” and “super” refer to the enclosing class

for (int i=0; i<n; i++) {


final int index = i; // final, a “free variable”

new Thread(
( ) -> {
System.out.println(“thread started by “ + this.toString()
+ “ object, with loop index “ + index);
}
);
} // for i=...
What are Lambdas, Actually ??

A lambda is represented in the JVM by an instance of an
anonymous and hidden class generated by the compiler, that
implements the target functional interface.

Lazy instantiation: object is not created unless used at runtime.


Example:
Comparator <String> comp = (s1, s2) -> {
if (s1.length() < s2.length()) return -1;
if (s1.length() > s2.length()) return +1;
return 0;
};
Class Object's Methods

Methods (toString, hashCode, equals, clone...)
are inherited by all classes → they are NOT
abstract.

A functional interface may include them:
@FunctionalInterface
interface Function1 <R,T> {
String toString(); // inherited from Object

boolean equals(Object ob); // inherited from Object

R apply(T t); // function with one param


};
Dealing with Exceptions

The lambda expression (code block) must
comply with the function signature in its
interface definition.

If a function does not throw checked exception,
than we must use try-catch:
new Thread(
( ) -> { // Runnable's method void run()
System.out.println(“runs in another thread”);
Thread.sleep(1000);
}
).start();
Trouble ! sleep() is declared
to throw checked InterruptedException
Dealing with Exceptions

The lambda expression (code block) must
comply with the function signature in its
interface definition.

If a function does not throw checked exception,
than we must use try-catch:
new Thread(
( ) -> { // Runnable's method void run()
System.out.println(“runs in another thread”);
try { Thread.sleep(1000);
} catch (InterruptedException ex) { }
}
).start(); Solution: try – catch block
Method References

If a proper method already exists, we can use it

Example:
 When mouse click on JButton, display the event.
With a lambda expression:
jButton.addActionListener(
event -> System.out.println(event)
);
 With a method reference:
jButton.addActionListener(
System.out::println
);
Method References

Method reference wrapped in compatible
lambda expression

Three cases:
 object::instanceMethod e.g. System.out::println
 Class::staticMethod e.g. Math::sqrt
 Class::instanceMethod e.g. Double::compareTo
Method References

object::instanceMethod

jButton.addActionListener(
event -> System.out.println(event)
);

same as:

jButton.addActionListener(
System.out::println
);
Instance method
object reference from class PrintStream
Method References

Class::staticMethod

Suppose we want to create a stream of Doubles, compute square
roots for them, then display them to System.out:

List<Double> dl = Arrays.asList(0.5, 1.0, 3.0, -2.0);



With lambda expression :

dl.stream().map( x -> Math.sqrt(x) )


.forEach( y -> System.out.println(y) );

Same with Class::staticMethod reference (Math::sqrt) :

dl.stream().map( Math::sqrt )
.forEach( y -> System.out.println(y) );
Method References

Class::instanceMethod
 Suppose the functional interface abstract function is defined
as:
Type1 instanceMethod(Type2 y, Type3 z);
 The first parameter in the lambda call becomes the target of
the method (the implicit parameter), the second becomes y,
the third becomes z, etc.

E.g. instance method compareTo() from class Double is defined
as:
int compareTo(Double other)
Method References

Class::instanceMethod (continued)

Sorting List <Double>:

List<Double> dl = Arrays.asList(3.0, 4.0, 2.0, 1.0);



Sorting with a lambda matching a Comparator<Double>:

Collections.sort(dl, (x,y) -> x.compareTo(y) );



Equivalent, with a method reference, Double::compareTo

Collections.sort(dl, Double::compareTo );
Constructor Reference

Similar to method references where the method name
is “new”.

Example: create array of JButtons from a list of labels
 Function stream() creates a stream of objects
 function map() calls the passed lambda on each stream
element and returns the new stream)
List<String> labels = new ArrayList<String>();

labels.add(“Hello”); labels.add(“Goodbye”);

Stream<JButton> stream = labels.stream().map( JButton::new);


List<Button> buttons = stream.collect(Collectors.toList());
same as
Stream<JButton> stream =labels.stream().map( (String s) -> new
JButton(s));
Further Reading

The java.util.function package

https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html


The Java Stream API
 https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

 Tutorials:
http://www.oracle.com/technetwork/articles/java/ma14-java-se-8-streams-2177646.html

 http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/

You might also like