COMP2511
Java: Lambda Expressions, Aggregate Operations,
Method References
Prepared by
Dr. Ashesh Mahidadia
Java Lambda Expressions
v Lambda expressions allow us to
v easily define anonymous methods,
v treat code as data and
v pass functionality as method argument.
v An anonymous inner class with only one method can be replaced by a lambda
expression.
v Lambda expressions can be used to implement an interface with only one abstract
method. Such interfaces are called Functional Interfaces.
v Lambda expressions offer functions as objects – a feature from functional programming.
v Lambda expressions are less verbose and offers more flexibility.
COMP2511: Lambda Expressions and Aggregate Ops 2
Java Lambda Expressions – Syntax
A lambda expression consists of the following:
v A comma-separated list of formal parameters enclosed in parentheses. No need to provide data
types, they will be inferred. For only one parameter, we can omit the parentheses.
v The arrow token, ->
v A body, which consists of a single expression or a statement block.
COMP2511: Lambda Expressions and Aggregate Ops 3
Method References
We can treat an existing method as an instance of a Functional Interface.
There are multiple ways to refer to a method, using :: operator.
v A static method (ClassName::methName)
v An instance method of a particular object (instanceRef::methName) or
(ClassName::methName)
v A class constructor reference (ClassName::new)
v Etc.
COMP2511: Lambda Expressions and Aggregate Ops 4
Function Interfaces in Java
v Functional interfaces, in the package java.util.function, provide predefined target types for
lambda expressions and method references.
v Each functional interface has a single abstract method, called the functional method for that functional
interface, to which the lambda expression’s parameter and return types are matched or adapted.
v Functional interfaces can provide a target type in multiple contexts, such as assignment context, method
invocation, etc. For example,
COMP2511: Lambda Expressions and Aggregate Ops 5
Lambda expression
Function Interfaces in Java
v There are several basic function shapes, including
v Function (unary function from T to R),
v Consumer (unary function from T to void),
v Predicate (unary function from T to boolean), and
v Supplier (nilary function to R).
v More information at the package summary page
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
COMP2511: Lambda Expressions and Aggregate Ops 6
Function Interfaces in Java: Examples
COMP2511: Lambda Expressions and Aggregate Ops 7
Function Interfaces in Java: Examples
COMP2511: Lambda Expressions and Aggregate Ops
Comparator using Lambda Expression: Example
COMP2511: Lambda Expressions and Aggregate Ops 9
Only one line!
Print using Lambda expression
Comparator using Lambda Expression: Another Example
COMP2511: Lambda Expressions and Aggregate Ops 10
Body
Parameters – o1 and o2
Pipelines and Streams
v A pipeline is a sequence of aggregate operations.
v The following example prints the male members contained in the collection roster with a
pipeline that consists of the aggregate operations filter and forEach:
COMP2511: Lambda Expressions and Aggregate Ops 11
for (Person p : roster) {
if (p.getGender() == Person.Sex.MALE) {
System.out.println(p.getName());
}
}
Traditional approach,
using a for-each loop:
roster
.stream()
.filter( e -> e.getGender() == Person.Sex.MALE )
.forEach( e -> System.out.println(e.getName()) );
Using pipeline and aggregate ops:
v Please note that, in a pipeline, operations are loosely coupled, they only rely on their incoming
streams and can be easily rearranged/replaced by other suitable operations.
v Just to clarify, the “.” (dot) operator in the above syntax has a very different meaning to the “.”
(dot) operator used with an instance or a class.
Pipelines and Streams
v A pipeline contains the following components:
• A source: This could be a collection, an array, a generator function, or an I/O channel. Such as
roster in the example.
• Zero or more intermediate operations. An intermediate operation, such as filter, produces a
new stream.
v A stream is a sequence of elements. The method stream creates a stream from a collection
(roster).
v The filter operation returns a new stream that contains elements that match its predicate. The
filter operation in the example returns a stream that contains all male members in the collection
roster.
v A terminal operation. A terminal operation, such as forEach, produces a non-stream result, such
as a primitive value (like a double value), a collection, or in the case of forEach, no value at all.
COMP2511: Lambda Expressions and Aggregate Ops 12
roster
.stream()
.filter( e -> e.getGender() == Person.Sex.MALE )
.forEach( e -> System.out.println(e.getName()) );
Pipelines and Streams: Example
v The above example calculates the average age of all male members contained in the collection
roster with a pipeline that consists of the aggregate operations filter, mapToInt, and average.
v The mapToInt operation returns a new stream of type IntStream (which is a stream that contains
only integer values). The operation applies the function specified in its parameter to each
element in a particular stream.
v As expected, the average operation calculates the average value of the elements contained in a
stream of type IntStream.
v There are many terminal operations such as average that return one value by combining the
contents of a stream. These operations are called reduction operations; see the section
Reduction for more information at https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html
COMP2511: Lambda Expressions and Aggregate Ops 13
double average = roster
.stream()
.filter(p -> p.getGender() == Person.Sex.MALE)
.mapToInt(Person::getAge)
.average()
.getAsDouble();
Pipelines and Streams: Another Example
COMP2511: Lambda Expressions and Aggregate Ops 14
End
COMP2511: Generics, Collections, Iterator 15