Streams and Lambdas
in Java 8
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0
1
Working Environment
- Integrated Development Environment (IDE)
- JDK 8
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 5
WORKING ENVIRONMENT
Integrated Development Environments
NetBeans by Oracle
https://netbeans.org/downloads/
NetBeans Any bundle will do
current version: 8.1
by Eclipse Foundation (formerly by IBM)
http://www.eclipse.org/downloads/
Eclipse current version: Eclipse Mars (4.5); with Neon available
Choose bundle „...Java EE Developers“
or „...Java Developers“
Intellij IDEA by JetBrains (commercial)
https://www.jetbrains.com/idea/
IDEA current version: 15
Students can get „Ultimate Edition“ for free
See https://www.jetbrains.com/student/
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 6
WORKING ENVIRONMENT
JDK 1.8 (JDK 8)
$ java -‐version
Java
java version "1.8.0_65"
Java(TM) SE Runtime
... JLS JDK Environment (build 1.8.0_65-‐
b17)
Java HotSpot(TM) 64-‐Bit
JRE Tools Server VM (build 25.65-‐b01,
javac.exe mixed mode)
JVM API
java.exe java.*
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 7
WORKING ENVIRONMENT
Dependency Management with Maven
Manage dependencies to 3rd party recursively and have your project
build automatically
e.g. use Google Guava Libraries by simply adding one dependency.
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 8
Basics Revisited
- Interfaces
- Collections Framework
- Anonymous Inner Classes
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 9
BASICS REVISITED
Interfaces
“Ordinary” interfaces
Marker interfaces (e.g. Serializable or Runnable)
Functional interfaces (annotated with @FunctionalInterface)
@interface classes (Annotations)
New in Java 8:
static methods
default methods
Default methods1
“A default method is a method that is declared in an interface with the default modifier; its body is always represented by a block. It
provides a default implementa=on for any class that implements the interface without overriding the method. Default methods are
dis=nct from concrete methods (§8.4.3.1), which are declared in classes.”
1[Gosling 2015, p. 288]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 10
BASICS REVISITED
Generics with <>
Generic class: Generic method:
T
<<interface>> Collec,ons
Comparable
+ <<T>> emptySet() : Set<T>
Definition
+ compareTo( other : T ) : int + <<U>> singleton( : U ) : Set<U>
public interface Comparable<T> { public class Collections {
public int compareTo(T other); public <T> Set<T> singleton(T obj)
} { ... }
}
class Student Set<String> name =
implements Comparable<Person> Collections.singleton("Max");
{
Usage
public int compareTo(Person other) Set<Person> persons =
{ Collections.<Person>emptySet();
// ...
}
}
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 11
BASICS REVISITED
Collections Framework
Two things to remember:
1. There are Lists, Sets, and Maps:
List<T>: ArrayList<T> or LinkedList<T>
Set<T>: TreeSet<T> or HashSet<T>
Map<K, V>: TreeMap<K, V> or HashMap<K, V>
2. Use “loosly coupled” references:
List<String> = new ArrayList<>();
Collections Framework1
“The collec=ons framework is a unified architecture for represen=ng and manipula=ng collec=ons, enabling them to be manipulated
independently of the details of their representa=on. It reduces programming effort while increasing performance. […]”
1[Oracle Corp. 2016]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 12
BASICS REVISITED
Collection interfaces (abridged)
<<interface>>
E <<interface>>
E
Collec,on Iterable
<<interface>>
E E <<interface>>
E <<interface>>
E
<<interface>>
List Queue Set SortedSet
<<interface>> <<interface>>
E
Deque NavigableSet
E
AbstractCollec,on
E
T
AbstractSet
AbstractList
E
AbstractSequen,alList
E
E
E
E
E
ArrayList Vector LinkedList HashSet TreeSet
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 13
BASICS REVISITED
Map interfaces (abridged)
K,V <<interface>>
K,V
<<interface>>
Map SortedMap
T
K,V <<interface>>
K,V
Dic,onary AbstractMap
NavigableMap
E
K,V
K,V
Hashtable HashMap TreeMap
E
E
Proper,es LinkedHashMap
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 14
COLLECTIONS
Utilities in class Collections
public static void reverse(List<?> list)
public static <E> Collection<E> checkedCollection(Collection<E> c,
Class<E> type)
public static <T> List<T> nCopies(int n, T o)
public static int frequency(Collection<?> c, Object o)
public static void shuffle(List<?> list)
public static void rotate(List<?> list, int distance)
public static void reverse(List<?> list)
public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)
public static <T> T min(Collection<? extends T> coll,
Comparator<? super T> comp)
// others:
Arrays.asList(Object... o)
Arrays.stream(T[] array)
Stream.of(T[] array)
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 16
BASICS REVISITED
Anonymous Inner Classes
public interface Comparator<T> { int compare (T obj1, T obj2); }
public class Collections {
public static <T> void sort(List<T> l, Comparator<? super T> c)
{...}
}
List<String> names = Arrays.asList("John", "Andrew", "Eve");
Collections.sort(names, new Comparator<String>() {
@Override public int compare(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
}
});
for(String name : names) System.out.print(name + " ");
// Eve John Andrew
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 17
Streams
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 18
STREAMS
Streams
A stream is “[…] a sequence of elements from a source that supports
aggregate operations”:1
§ “Sequence of elements: A stream provides an interface to a sequenced set
of values of a specific element type. However, streams don’t actually store
elements; they are computed on demand.
§ Source: Streams conamounte from a data-providing source such as
collections, arrays, or I/O resources.
§ Aggregate operations: Streams support SQL-like operations and common
operations from functional programing languages, such as filter, map,
reduce, find, match, sorted, and so on.”
1[Urma (2014a), section “Getting Started With Streams”]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 19
STREAMS
Streams
§ are not data structure
§ do not contain storage for data
§ are “pipelines” for streams of data (i.e. of objects)
§ while in the pipeline data undergo transformation
(without changing the data structure holding it)
§ wrap collections (lists, set, maps)
§ read data from it
§ work on copies
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 20
STREAMS
How do data get into streams?
Streams are mainly generated based on collections:
List<String> names = Arrays.asList("John", "George", "Sue");
Stream<String> stream1 = names.stream();
Stream<String> stream2 = Stream.of("Tom", "Rita", "Mae");
Stream<String> stream3;
stream2 = Arrays.stream( new String[]{"Lisa", "Max", "Anna"} );
Or with builder pattern:
Stream<String> stream4 = Stream.<String>builder()
.add("Mike")
.add("Sandra").build();
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 21
STREAMS
How do data get out of streams?
§ The Streaming API provides so called “finalizing” methods
forEach
(i.e. methods that do not return stream objects) toArray
collect
reduce
min
max
count
anyMatch
noneMatch
findFirst
findAny
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 22
STREAMS
Streaming example
“Take all names from the stream that start with the letter “J”, map the names
into capital letters, skip one, and collect them into a new set”
List<String> names = Stream.of("John","George","Joe","Sue","James");
Stream<String> stream1 = names.stream();
______ = stream1.filter( ___________ )
.map( ___________ )
.skip( ___________ )
.collect( ___________ );
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 23
Lambda Expressions and
Functional Interfaces
- Lambdas
- Functional Interfaces
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 24
LAMBDA EXPRESSIONS
Lambdas or Closures
“Lambda” = “closure” = record storing a function (functionality,
method) and its environment (but without a class or method name)
Roughly: anonymous method
Lambdas represent source code - not data and not object state!
Syntax:
( parameter list ) -‐> { expression(s) }
Examples:
(int x, int y) -‐> { return x + y; }
(long x) -‐> { return x * 2; }
() -‐> { String msg = "Lambda"; System.out.println(msg); }
For details on “functional programming” cf. [Huges 1984] or [Turner 2013]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 25
LAMBDA EXPRESSIONS
Lambdas and functional interfaces
Functional interfaces are so called SAM types (single abstract method)
A functional interface has exactly one abstract method, e.g. Runnable,
Comparator<T>, or Comparable<T>
Functional interfaces can define 0..* default methods and 0..* static
methods
Using the @FunctionalInterface annotation on classes the compiler
is required to generate an error message if it is no interface and it
doesn’t define exactly one SAM.
@FunctionalInterface
public interface Counter<T> {
int count(T obj);
}
Task: Create a first lambda expression that counts the letters within a String
Counter<String> strCount = (String s) -‐> { return s.length(); };
[https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 26
LAMBDA EXPRESSIONS
Your first lambda with Comparator<T>
@FunctionalInterface
public interface Comparator<T> { int compare(T obj1, T obj2); }
public class Collections {
public static <T> void sort(List<T> l, Comparator<? super T> c)
{...}
}
Your task:
Prepare your first lambda expression
to compare two String objects by length
List<String> names = Arrays.asList("John", "Andrew", "Eve");
Collections.sort(names, ???? );
for(String name : names) System.out.print(name + " ");
// Eve John Andrew
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 27
LAMBDA EXPRESSIONS
Functional interfaces in JDK
Selection of most used interfaces from package java.util.function:
// Computes a single input with no result
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {...}
}
// Represents a supplier of results.
interface Supplier<T> {
T get();
}
// Computes a single output, prodeces output of different type
interface Function<T,R> {
R apply(T t);
default <V> Function<T,V> andThen(Function<? super R,? extends V> after) {...}
default <V> Function<V,R> compose(Function<? super V,? extends T> before) {...}
}
// Represents a predicate (boolean-‐valued function) of one argument
interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {...}
default Predicate<T> negate() {...}
// ...
}
[https://docs.oracle.com/javase/8/docs/api/java/util/function/package-‐amountmary.html]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 28
LAMBDA EXPRESSIONS
Type inference
Lambda expressions allow for minimal syntax if compiler can deduct
type information (so called type inference), e.g.:
@FunctionalInterface
public interface BiFunction<T, U, R> {
R = Integer could be inferred from return type of
R apply(T t, U u);
expression t.length() + u.length() à Integer
} (e.g. when used directly in typed method call)
BiFunction<String, Object, Integer> bf;
compiler can infer types from declaration of f
bf = (String txt, Object obj) -‐> { return t.length() + u.hashCode() ); }
// can be even shorter:
bf = (txt, obj) -‐> t.length() + u.hashCode(); // se below
for single return statements keyword return
Further syntax shortening examples: together with {}-pair can be dropped
(int x, int y) -‐> { return x * y; } // shorter: (x, y) -‐> x * y
(long x) -‐> { return x * 2; } // shortest: x -‐> x * 2
( )-pair can be dropped with only one parameter
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 29
LAMBDA EXPRESSIONS
Lambda as parameters and return types
Further examples for type inference using Comparator<T> as
functional interface:
List<String> names = Arrays.asList("Ahab", "George", "Sue");
Collections.sort(names, (s1, s2) -‐> s1.length() -‐ s2.length() );
T :: String can be deducted from names being a List<String>
Signature of Collections::sort method is:
public static <T> void sort(List<T> list, Comparator<? super T> c)
Collections.sort(names, createComparator() );
public Comparator<String> createComparator() {
return (s1, s2) -‐> s1.length() -‐ s2.length();
}
Statement returned here is of functional
interface type Comparator<String>
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 30
LAMBDA EXPRESSIONS
Method references (“function pointers”)
Syntax: Classname::methodName objectReferenceName::methodName
Lambdas can be replaced by method references whenever there
would not further actions within the the lambda
Examples:
Reference Method reference… …replacing Lambda
sta=c method String::valueOf obj -‐> String.valueOf(obj)
instance method String::compareTo (s1, s2) -‐> s1.comapreTo(s2)
(via class)
instance method person::getName () -‐> person.getName()
(via object ref)
Constructor ArrayList::new () -‐> new ArrayList<>()
[Table taken from Inden 2015, p. 812]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 31
Streaming API
- Creating Streams
- Fluently working with streams
- Finalize Streams
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 32
STREAMING API
Stream ops I use most
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 33
STREAMING API
Stream operations
Source => STREAM => OP1 => OP2 => ... => OPn => Result
Create “lazy” Intermediate Terminal
not performed
until
// interface Collection // stateless forEach
stream() filter toArray
parallelStream() map collect
flatMap reduce
// Utiliy class peek min Check the
Arrays.stream(...) //stateful max factory
Arrays.stream(...).parallel() distinct methods in
count
Collectors for
sorted anyMatch a set of
limit noneMatch Collector-
skip findFirst Operations
Return an object findAny
reference of Type
Stream<E> Check the java doc for more information on parameter types
and return types;
intermediate operations return (of course) Stream<E> object
references [Inden 2015, p. 825]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 34
STREAMING API
Class Optional<T>
The class Optional<T> is a container wrapped around an object and is useful
if you do not know whether its content is null or not (e.g. when using in
fluent programming style).
T
<<interface>>
Optional
+ get() : T
+ isPresent() : boolean
+ ifPresent( : Consumer<? super T> )
+ orElse( other : T ) : T
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 35
STREAMING API
Example
List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t : transactions){
if(t.getType() == Transaction.GROCERY) {
groceryTransactions.add(t);
}
“old fashioned”
}
Collections.sort(groceryTransactions, new Comparator(){
@Override
public int compare(Transaction t1, Transaction t2){
return t2.getValue().compareTo(t1.getValue());
}
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t : groceryTransactions) {
transactionsIds.add(t.getId());
}
List<Integer> transactionsIds =
Stream like
transactions.stream()
.filter(t -‐> t.getType() == Transaction.GROCERY)
.sorted(comparing(Transaction::getValue).reversed())
.map(Transaction::getId)
.collect(toList());
[taken from Urma (2014a)]
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 36
Bibliography
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 37
Gosling, J. et al. (2015): The Java® Language Specification – Java SE 8 Edition, March
2015, http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf
Huges, J. (1984): Why Functional Programming Matters, rev. ed., http://
www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf
Oracle Corp. (2016): The Collections Framework, Website, http://docs.oracle.com/
javase/8/docs/technotes/guides/collections/
Turner, D. (2013): Some History of Functional Programming Languages. In: Loidl, H.-
W. and Pena, R.: Trends in Functional Programming: 13th International Symposium,
TFP 2012, St. Andrews, UK, June 12-14, 2012, Revised Selected Papers, p. 1-20.
Springer: Berlin and Heidelberg
Urma, R.-G. (2014a): Processing Data with Java SE 8 Streams, Part 1, Java Magazine,
March/April 2014, http://www.oracle.com/technetwork/articles/java/ma14-‐
java-‐se-‐8-‐streams-‐2177646.html
Urma, R.-G. (2014b): Part 2: Processing Data with Java SE 8 Streams, Java Magazine,
May/June 2014, http://www.oracle.com/technetwork/articles/java/architect-‐
streams-‐pt2-‐2227132.html
STREAMS AND LAMBDAS IN JAVA 8 | © PROF. DR. DANIEL JOBST | WS 2015/16 | VERSION 1.0 38