Java 8 Stream API
Outline
• Java 8
– Default Methods
– Functional Interfaces
– Lambda Expressions
– Method References
Default Methods
• In Context of Support For Streams
– Java 8 needed to add functionality to existing
Collection interfaces to support Streams (stream(),
forEach())
Default Methods
• Problem
– Pre-Java 8 interfaces couldn’t have method bodies.
– The only way to add functionality to Interfaces was
to declare additional methods which would be
implemented in classes that implement the
interface
– It is impossible to add methods to an interface
without breaking the existing implementation
Default Methods
• Solution
– Default Methods!
– Java 8 allows default methods to be added to interfaces
with their full implementation
– Classes which implement the interface don’t have to
have implementations of the default method
– Allows the addition of functionality to interfaces while
preserving backward compatibility
Default Methods
• Example
public interface A {
default void foo(){
[Link]("Calling [Link]()");
}
public class Clazz implements A {}
Clazz clazz = new Clazz();
[Link](); // Calling [Link]()
Functional Interfaces
• Interfaces with only one abstract method.
• With only one abstract method, these interfaces can be easily
represented with lambda expressions
• Example
@FunctionalInterface
public interface SimpleFuncInterface {
public void doWork();
Default test() {sout(“hello");};
static test1() {sout}
}
Lambda expressions
• A more brief and clearly expressive way to
implement functional interfaces
• Format: <Argument List> -> <Body>
Method References
• Event more brief and clearly expressive way to
implement functional interfaces
• Format: <Class or Instance>::<Method>
Characteristics of Streams
• Streams are not related to InputStreams, OutputStreams, etc.
• Streams are NOT data structures but are wrappers around
Collection that carry values from a source through a pipeline of
operations.
• Streams are designed for lambdas
• Streams can easily be output as arrays or lists
• Streams employ lazy evaluation
• Streams are parallelizable
Creating Streams
• From individual values
– [Link](val1, val2, …)
• From array
– [Link](someArray)
– [Link](someArray)
• From List (and other Collections)
– [Link]()
– [Link]()
Common Functional Interfaces Used
• Predicate<T>
– Represents a predicate (boolean-valued function) of one argument
– Functional method is boolean Test(T t)
• Returns true if the input argument matches the predicate, otherwise false
• Supplier<T>
– Represents a supplier of results
– Functional method is T get()
• Returns a result of type T
• Function<T,R>
– Represents a function that accepts one argument and produces a result
– Functional method is R apply(T t)
• Applies this function to the given argument (T t)
• Returns the function result
• Consumer<T>
– Represents an operation that accepts a single input and returns no result
– Functional method is void accept(T t)
• Performs this operation on the given argument (T t)
Common Functional Interfaces Used
• BiPredicate<T,U>
– Represents a predicate (boolean-valued function) of two argument
– Functional method is boolean Test(T t, U u)
• Returns true if the input arguments matches the predicate, otherwise false
• BiFunction<T,U,R>
– Represents an operation that accepts two arguments and produces a result
– Functional method is R apply(T t, U u)
• Applies this function to the given arguments (T t, U u)
• Returns the function result
• BiConsumer<T,U>
– Represents an operation that accepts a two input and returns no result
– Functional method is void accept(T t, U u)
• Performs this operation on the given argument (T t, U u)
• Comparator<T>
– Compares its two arguments for order.
– Functional method is int compareTo(T o1, T o2)
• Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the
second.
Common Functional Interfaces Used
• UnaryOperator<T>
– Represents an operation on a single operands that produces a result of the same type
as its operand
– Functional method is R [Link](T t)
• Applies this function to the given argument (T t) where R,T are of the same type
• Returns the function result
• BinaryOperator<T>
– Extends BiFunction<T, U, R>
– Represents an operation upon two operands of the same type, producing a result of
the same type as the operands
– Functional method is R [Link](T t, U u)
• Applies this function to the given arguments (T t, U u) where R,T and U are of the same type
• Returns the function result
Stream Pipeline
• A Stream is processed through a pipeline of
operations
• A Stream starts with a source data structure
• Intermediate methods are performed on the
Stream elements. These methods produce
Streams and are not processed until the
terminal method is called.
Stream Pipeline
• Intermediate Methods
map, filter, distinct, sorted, peek, limit
• Terminal Methods
forEach, toArray, reduce, collect, min,
max, count, anyMatch, allMatch, noneMatch,
findFirst, findAny
Optional<T> Class
• A container which may or may not contain a non-null
value
• Common methods
– isPresent() – returns true if value is present
– Get() – returns value if present
– orElse(T other) – returns value if present, or other
– orElseThrow (Exception ex) – returns value if present, or throw an
exception
– ifPresent(Consumer) – runs the lambda if value is present
Common Stream API Methods Used
• Void forEach(Consumer) // terminal
method
– Easy way to loop over Stream elements
– You supply a lambda for forEach and that lambda is
called on each element of the Stream
– Related peek method (intermediate method) does the
exact same thing, but returns the original Stream
– Stream -> Stream -> Stream
Common Stream API Methods Used
• Void forEach(Consumer)
–Example
[Link](Employee e ->
[Link]([Link]() * 11/10))
Give all employees a 10% raise
Common Stream API Methods Used
• Void forEach(Consumer)
–Vs. For Loops
List<Employee> employees = getEmployees();
for(Employee e: employees) {
[Link]([Link]() * 11/10);
}
–Advantages of forEach
Common Stream API Methods Used
• Stream<T> map(Function)
– Produces a new Stream that is the result of applying
a Function to each element of original Stream
– Example
[Link](EmployeeUtils::findEmployeeById)
Create a new Stream of Employee ids
Common Stream API Methods Used
• Stream<T> filter(Predicate)
– Produces a new Stream that contains only the
elements of the original Stream that pass a given
test
– Example
[Link](e -> [Link]() > 100000)
Produce a Stream of Employees with a salary greater
Common Stream API Methods Used
• Optional<T> findFirst()
– Returns an Optional for the first entry in the
Stream
– Example
[Link](…).findFirst().orElseThrow(UserN
otFoundExcep)
Get the first Employee entry that passes the filter
Common Stream API Methods Used
• Object[] toArray(Supplier)
– Reads the Stream of elements into a an array
– Example
Employee[] empArray =
[Link](Employee[]::new);
Create an array of Employees out of the Stream
of Employees
Common Stream API Methods Used
• List<T> collect([Link]())
• Reads the Stream of elements into a List or any other
collection
– Example
List<Employee> empList =
[Link]([Link]());
Create a List of Employees out of the Stream of
Employees
Common Stream API Methods Used
• T reduce(T identity, BinaryOperator)
• T reduce(BinaryOperator)
• You start with a seed (identity) value, then
combine this value with the first Entry in the
Stream, combine the second entry of the Stream,
etc.
– Example
Common Stream API Methods Used
• Stream<T> limit(long maxSize)
• Limit(n) returns a stream of the first n
elements
– Example
[Link](10)
Common Stream API Methods Used
• Stream<T> skip(long n)
• skip(n) returns a stream starting with the
n’th element
–Example
[Link](5)
Common Stream API Methods Used
• Stream<T> sorted(Comparator)
– Returns a stream consisting of the elements of this
stream, sorted according to the provided Comparator
– Example
[Link](…).filter(…).limit(…)
.sorted((e1, e2) -> [Link]() - [Link]())
Employees sorted by salary
Common Stream API Methods Used
• Boolean anyMatch(Predicate), allMatch(Predicate),
noneMatch(Predicate)
– Returns true if Stream passes, false otherwise
– Lazy Evaluation
• anyMatch processes elements in the Stream one element at a time until it finds a
match according to the Predicate and returns true if it found a match
• allMatch processes elements in the Stream one element at a time until it fails a match
according to the Predicate and returns false if an element failed the Predicate
• noneMatch processes elements in the Stream one element at a time until it finds a
match according to the Predicate and returns false if an element matches the
Predicate
– Example
[Link](e -> [Link]() > 500000)
Common Stream API Methods Used
• long count()
– Returns the count of elements in the Stream
– Example
[Link](somePredicate).co
unt()
How many Employees match the criteria?
Questions?
[Link]
functional-programming-with-java