0% found this document useful (0 votes)
11 views

Java - Lambda Expressions & Streams API

Uploaded by

pavan.n
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

Java - Lambda Expressions & Streams API

Uploaded by

pavan.n
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

Java - Lambda Expressions & Streams API

Overview

Purpose

This tutorial introduces the new lambda expressions included in Java Platform Standard Edition 8 (Java
SE 8).

Time to Complete

Approximately 1 hour

Introduction

Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and
concise way to represent one method interface using an expression. Lambda expressions also improve
the Collection libraries making it easier to iterate through, filter, and extract data from a Collection. In
addition, new concurrency features improve performance in multicore environments.

This Oracle by Example (OBE) provides an introduction to lambda expressions included in Java SE 8. An
introduction to anonymous inner functions is provided, followed by a discussion of functional interfaces
and the new lambda syntax. Then, examples of common usage patterns before and after lambda
expressions are shown.

The next section reviews a common search use case and how Java code can be improved with the
inclusion of lambda expressions. In addition, some of the common functional
interfaces, Predicate and Function, provided in java.util.function are shown in action.

The OBE finishes up with a review of how the Java collection has been updated with lambda expressions.

The source code for all examples is provided to you.

Hardware and Software Requirements

The following is a list of hardware and software requirements:

 Java Development Kit (JDK 8) early access

 NetBeans 7.4

Prerequisites

To run the examples, you must have an early access version of JDK 8 and a copy of NetBeans 7.4 or later.
Links can be found at the main Lambda site. For your convenience, here are the direct links.

 Java Development Kit 8 (JDK8) Early Access

o Recommended: Download the JDK 8 API Docs from the same page.

 NetBeans 7.4 or later. Version 7.4 of NetBeans includes support for JDK 8.

Note: Builds are provided for all major operating systems. This OBE was developed using Linux Mint 13
(Ubuntu/Debian).
Install JDK8 and NetBeans following the instructions provided with the downloads. Add
the bin directories for Java and NetBeans to your PATH.

Background

In Java, anonymous inner classes provide a way to implement classes that may occur only once in an
application. For example, in a standard Swing or JavaFX application a number of event handlers are
required for keyboard and mouse events. Rather than writing a separate event-handling class for each
event, you can write something like this.

Otherwise, a separate class that implements ActionListener is required for each event. By creating the
class in place, where it is needed, the code is a little easier to read. The code is not elegant, because
quite a bit of code is required just to define one method.

Functional Interfaces

The code that defines the ActionListener interface, looks something like this:

The ActionListener example is an interface with only one method. With Java SE 8, an interface that
follows this pattern is known as a "functional interface."

Note: This type of interface, was previously known as a Single Abstract Method type (SAM).

Using functional interfaces with anonymous inner classes are a common pattern in Java. In addition to
the EventListener classes, interfaces like Runnable and Comparator are used in a similar manner.
Therefore, functional interfaces are leveraged for use with lambda expressions.

Lambda Expression Syntax

Lambda expressions address the bulkiness of anonymous inner classes by converting five lines of code
into a single statement. This simple horizontal solution solves the "vertical problem" presented by inner
classes.
A lambda expression is composed of three parts.

The body can be either a single expression or a statement block. In the expression form, the body is
simply evaluated and returned. In the block form, the body is evaluated like a method body and a return
statement returns control to the caller of the anonymous method. The break and continue keywords are
illegal at the top level, but are permitted within loops. If the body produces a result, every control path
must return something or throw an exception.

Take a look at these examples:

The first expression takes two integer arguments, named x and y, and uses the expression form to
return x+y. The second expression takes no arguments and uses the expression form to return an
integer 42. The third expression takes a string and uses the block form to print the string to the console,
and returns nothing.

With the basics of syntax covered, let's look at some examples.

Lambda Examples

Here are some common use cases using the previously covered examples.

Runnable Lambda

Here is how you write a Runnable using lambdas.


In both cases, notice that no parameter is passed and is returned. The Runnable lambda expression,
which uses the block format, converts five lines of code into one statement.

Comparator Lambda

In Java, the Comparator class is used for sorting collections. In the following example,
an ArrayList consisting of Person objects is sorted based on surName. The following are the fields
included in the Person class.

The following code applies a Comparator by using an anonymous inner class and a couple lambda
expressions.
Lines 17 - 21 are easily replaced by the lambda expression on line 32. Notice that the first lambda
expression declares the parameter type passed to the expression. However, as you can see from the
second expression, this is optional. Lambda supports "target typing" which infers the object type from
the context in which it is used. Because we are assigning the result to a Comparator defined with a
generic, the compiler can infer that the two parameters are of the Person type.

Listener Lambda

Finally, let's revisit the ActionListener example.


Notice that the lambda expression is passed as a parameter. Target typing is used in a number of
contexts including the following:

 Variable declarations

 Assignments

 Return statements

 Array initializers

 Method or constructor arguments

 Lambda expression bodies

 Conditional expressions ?:

 Cast expressions

Improving Code with Lambda Expressions

This section builds upon the previous examples to show you how lambda expressions can improve your
code. Lambdas should provide a means to better support the Don't Repeat Yourself (DRY) principle and
make your code simpler and more readable.

A Common Query Use Case

A common use case for programs is to search through a collection of data to find items that match a
specific criteria. In the excellent "Jump-Starting Lambda" presentation at JavaOne 2012, Stuart Marks
and Mike Duigou walk though just such a use case. Given a list of people, various criteria are used to
make robo calls (automated phone calls) to matching persons. This tutorial follows that basic premise
with slight variations.

In this example, our message needs to get out to three different groups in the United States:
 Drivers: Persons over the age of 16

 Draftees: Male persons between the ages of 18 and 25

 Pilots (specifically commercial pilots): Persons between the ages of 23 and 65

The actual robot that does all this work has not yet arrived at our place of business. Instead of calling,
mailing or emailing, a message is printed to the console. The message contains a person's name, age,
and information specific to the target medium (for example, email address when emailing or phone
number when calling).

Person Class

Each person in the test list is defined by using the Person class with the following properties:

The Person class uses a Builder to create new objects. A sample list of people is created with
the createShortList method. Here is a short code fragment of that method. Note: All source code for this
tutorial is included in a NetBeans project that is linked at the end of this section.
A First Attempt

With a Person class and search criteria defined, you can write a RoboContact class. One possible solution
defines a method for each use case:

RoboContactsMethods.java
Notice that a Predicate is set up for each group: allDrivers, allDraftees, and allPilots. You can pass any of
these Predicate interfaces to the contact methods. The code is compact and easy to read, and it is not
repetitive.

The java.util.function Package

The java.util.function Package

Of course, Predicate is not the only functional interface provided with Java SE 8. A number of standard
interfaces are designed as a starter set for developers.

 Predicate: A property of the object passed as argument

 Consumer: An action to be performed with the object passed as argument

 Function: Transform a T to a U

 Supplier: Provide an instance of a T (such as a factory)

 UnaryOperator: A unary operator from T -> T

 BinaryOperator: A binary operator from (T, T) -> T

In addition, many of these interfaces also have primitive versions. This should give you a great starting
point for your lambda expressions.
Eastern Style Names and Method References

When working on the previous example, I decided it would be nice to have a flexible printing system for
the Person class. One feature requirement is to display names in both a western style and an eastern
style. In the West, names are displayed with the given name first and the surname second. In many
eastern cultures, names are displayed with the surname first and the given name second.

An Old Style Example

Here is an example of how to implement a Person printing class without lambda support.

Person.java

A method exists for each style that prints out a person.

The Function Interface

The Function interface is useful for this problem. It has only one method apply with the following
signature:

public R apply(T t){ }

It takes a generic class T and returns a generic class R. For this example, pass the Person class and return
a String. A more flexible print method for person could be written like this:

Person.java

That is quite a bit simpler. A Function is passed to the method and a string returned. The apply method
processes a lambda expression which determines what Person information is returned.

How are the Functions defined? Here is the test code that calls the previous method.

NameTestNew.java
The first loop just prints given name and the email address. But any valid expression could be passed to
the printCustom method. Eastern and western print styles are defined with lambda expressions and
stored in a variable. The variables are then passed to the final two loops. The lambda expressions could
very easily be incorporated into a Map to make their reuse much easier. The lambda expression
provides a great deal of flexibility.

Sample Output

Here is some sample output from the program.

==== NameTestNew02 ===


===Custom List===
Name: Bob EMail: [email protected]
Name: Jane EMail: [email protected]
Name: John EMail: [email protected]
Name: James EMail: [email protected]
Name: Joe EMail: [email protected]
Name: Phil EMail: phil.smith@examp;e.com
Name: Betty EMail: [email protected]

===Western List===

Name: Bob Baker


Age: 21 Gender: MALE
EMail: [email protected]
Phone: 201-121-4678
Address: 44 4th St, Smallville, KS 12333

Name: Jane Doe


Age: 25 Gender: FEMALE
EMail: [email protected]
Phone: 202-123-4678
Address: 33 3rd St, Smallville, KS 12333

Name: John Doe


Age: 25 Gender: MALE
EMail: [email protected]
Phone: 202-123-4678
Address: 33 3rd St, Smallville, KS 12333

Name: James Johnson


Age: 45 Gender: MALE
EMail: [email protected]
Phone: 333-456-1233
Address: 201 2nd St, New York, NY 12111

Name: Joe Bailey


Age: 67 Gender: MALE
EMail: [email protected]
Phone: 112-111-1111
Address: 111 1st St, Town, CA 11111

Name: Phil Smith


Age: 55 Gender: MALE
EMail: phil.smith@examp;e.com
Phone: 222-33-1234
Address: 22 2nd St, New Park, CO 222333

Name: Betty Jones


Age: 85 Gender: FEMALE
EMail: [email protected]
Phone: 211-33-1234
Address: 22 4th St, New Park, CO 222333
===Eastern List===

Name: Baker Bob


Age: 21 Gender: MALE
EMail: [email protected]
Phone: 201-121-4678
Address: 44 4th St, Smallville, KS 12333

Name: Doe Jane


Age: 25 Gender: FEMALE
EMail: [email protected]
Phone: 202-123-4678
Address: 33 3rd St, Smallville, KS 12333

Name: Doe John


Age: 25 Gender: MALE
EMail: [email protected]
Phone: 202-123-4678
Address: 33 3rd St, Smallville, KS 12333

Name: Johnson James


Age: 45 Gender: MALE
EMail: [email protected]
Phone: 333-456-1233
Address: 201 2nd St, New York, NY 12111

Name: Bailey Joe


Age: 67 Gender: MALE
EMail: [email protected]
Phone: 112-111-1111
Address: 111 1st St, Town, CA 11111

Name: Smith Phil


Age: 55 Gender: MALE
EMail: phil.smith@examp;e.com
Phone: 222-33-1234
Address: 22 2nd St, New Park, CO 222333

Name: Jones Betty


Age: 85 Gender: FEMALE
EMail: [email protected]
Phone: 211-33-1234
Address: 22 4th St, New Park, CO 222333

Resources
The NetBeans project with the source code for the examples in this section is included in the following
zip file.

LambdaFunctionExamples.zip

Lambda Expressions and Collections

The previous section introduced the Function interface and finished up examples of basic lambda
expression syntax. This section reviews how lambda expressions improve the Collection classes.

Lambda Expressions and Collections

In the examples created so far, the collections classes were used quite a bit. However, a number of new
lambda expression features change the way collections are used. This section introduces a few of these
new features.

Class Additions

The drivers, pilots, and draftees search criteria have been encapsulated in the SearchCriteria class.

SearchCriteria.java
The Predicate based search criteria are stored in this class and available for our test methods.

Looping

The first feature to look at is the new forEach method available to any collection class. Here are a couple
of examples that print out a Person list.

Test01ForEach.java

The first example shows a standard lambda expression which calls the printWesternName method to
print out each person in the list. The second example demonstrates a method reference. In a case
where a method already exists to perform an operation on the class, this syntax can be used instead of
the normal lambda expression syntax. Finally, the last example shows how the printCustom method can
also be used in this situation. Notice the slight variation in variable names when one lambda expression
is included in another.

You can iterate through any collection this way. The basic structure is similar to the enhanced for loop.
However, including an iteration mechanism within the class provides a number of benefits.

Chaining and Filters

In addition to looping through the contents of a collection, you can chain methods together. The first
method to look at is filter which takes a Predicate interface as a parameter.

The following example loops though a List after first filtering the results.

Test02Filter.java
The first and last loops demonstrate how the List is filtered based on the search criteria. The output
from the last loop looks like following:

Getting Lazy

These features are useful, but why add them to the collections classes when there is already a perfectly
good for loop? By moving iteration features into a library, it allows the developers of Java to do more
code optimizations. To explain further, a couple of terms need definitions.

 Laziness: In programming, laziness refers to processing only the objects that you want to
process when you need to process them. In the previous example, the last loop is "lazy" because
it loops only through the two Person objects left after the List is filtered. The code should be
more efficient because the final processing step occurs only on the selected objects.

 Eagerness: Code that performs operations on every object in a list is considered "eager". For
example, an enhanced for loop that iterates through an entire list to process two objects, is
considered a more "eager" approach.

By making looping part of the collections library, code can be better optimized for "lazy" operations
when the opportunity arises. When a more eager approach makes sense (for example, computing a sum
or an average), eager operations are still applied. This approach is a much more efficient and flexible
than always using eager operations.

The stream Method


In the previous code example, notice that the stream method is called before filtering and looping begin.
This method takes a Collection as input and returns a java.util.stream.Stream interface as the output.
A Stream represents a sequence of elements on which various methods can be chained. By default, once
elements are consumed they are no longer available from the stream. Therefore, a chain of operations
can occur only once on a particular Stream. In addition, a Stream can be serial(default) or parallel
depending on the method called. An example of a parallel stream is included at the end of this section.

Mutation and Results

As previously mentioned, a Stream is disposed of after its use. Therefore, the elements in a collection
cannot be changed or mutated with a Stream. However, what if you want to keep elements returned
from your chained operations? You can save them to a new collection. The following code shows how to
do just that.

Test03toList.java

The collect method is called with one parameter, the Collectors class. The Collectors class is able to
return a List or Set based on the results of the stream. The example shows how the result of the stream
is assigned to a new List which is iterated over.

Calculating with map

The map method is commonly used with filter. The method takes a property from a class and does
something with it. The following example demonstrates this by performing calculations based on age.

Test04Map.java
And the output from the class is:

The program calculates the average age of pilots in our list. The first loop
demonstrates the old style of calculating the number by using a for loop. The second loop uses
the map method to get the age of each person in a serial stream. Notice that totalAge is a long.
The map method returns an IntSteam object, which contains a sum method that returns a long.

Note: To compute the average the second time, calculating the sum of ages is unnecessary. However, it
is instructive to show an example with the sum method.
The last loop computes the average age from the stream. Notice that the parallelStream method is used
to get a parallel stream so that the values can be computed concurrently. The return type is a bit
different here as well.

Resources

The NetBeans project with source code for the examples is in the following zip file.

LambdaCollectionExamples.zip

Summary

In this tutorial, you learned how to use:

 Anonymous inner classes in Java.

 Lambda expressions to replace anonymous inner classes in Java SE 8.

 The correct syntax for lambda expressions.

 A Predicate interface to perform searches on a list.

 A Function interface to process an object and produce a different type of object.

 New features added to Collections in Java SE 8 that support lambda expressions.

Resources

For further information on Java SE 8 and lambda expressions, see the following:

 Java 8

 Project Lambda

 State of the Lambda

 State of the Lambda Collections

 Jump-Starting Lambda JavaOne 2012 (You Tube)

 To learn more about Java and related topics check out the Oracle Learning Library.

Credits

 Lead Curriculum Developer: Michael Williams

 QA: Juan Quesada Nunez

You might also like