Please enable JavaScript.
Coggle requires JavaScript to display documents.
Chapter 4. FUNCTIONAL PROGRAMMING (Return an Optional (isPresent() (Empty,…
Chapter 4. FUNCTIONAL PROGRAMMING
Using Variables in Lambdas
accessible
static variables
instance variables
effectively final method parameters
effectively final local variables
Working with Build-In Functional Interfaces
Supplier<T>
# Parameters
0
Return Type
T
Generate or supply values without taking any input
Single Abstract Method
get
Example
Supplier<LocalDate> s1 = LocalDate::now;
LocalDate d1 = s1.get();
System.out.println(d1);
Consumer<T> and BiConsumer<T,U>
Do something with one (or two) parameter but not return anything
# Parameters
Consumer: 1(T)
BiConsumer: 2(T,U)
Return Type
void
Single Abstract Method
accept
Example
Cosumer<String> c1 = System.out::println;
c1.accept("Annie);
Map<String, Integer> map = new HashMap<>();
BiCosumer<String, Integer> b1 = map::put;
b1.accept("chick",1);
Function<T,R> and BiFunction<T,U,R>
Turn one parameter into value of a potentially different type and return it
# Parameters
Function: 1(T)
BiFunction: 2(T,U)
Return Type
R
Single Abstract Method
apply
Examples
Function<String, Integer> f1 = String::length;
System.out.println(f1.apply("chuck"));
BiFunction<String, String, String> b1 = String::concat;
System.out.println(b1.apply("baby ", "chick"));
UnaryOperator<T> and BinaryOperator<T>
Special case of
Function
which all type parameters is the
same
type
# Parameters
UnaryOperator: 1(T)
BinaryOperator: 2(T,T)
Return Type
T
Single Abstract Method
apply
Examples
BinaryOperator<String> b1 = String::concat;
System.out.println(b1.apply("baby ", "chick"));
UnaryOperator<String> u1 = String::toUpperCase;
System.out.println(u1.apply("chirp));
Predicate<T> and BiPredicate<T,U>
Filtering or Matching
# Parameters
Predicate: 1(T)
BiPredicate: 2(T,U)
Return Type
boolean
Single Abstract Method
test
Examples
Predicate<String> p1 = String::isEmpty();
System.out.println(p1.test(""));
BiPredicate<String, String> b1 = String::startsWith;
System.out.println(b1.test("chickern","chick"));
Return an
Optional
isPresent()
Empty
Return false
Contain value
Return true
orElse(T other)
Empty
Return other parameter
Contain value
Return value
ifPresent(Consume c)
Empty
Does nothing
Contain value
Call
Consumer
c with value
orElseGet(Supplier s)
Empty
Return result of calling
Supplier
Contain value
Return value
get()
Empty
Throw an exception
Contain value
Return value
orElseThrow(Supplier s)
Empty
Throw exception created by calling Supplier
Contain value
Return value
Using Streams
Creating
Stream Sources
Create a finite stream
Stream<Integer> empty = Stream.empty();
Stream<Integer> fromArray = Stream.of(1,2,3);
Create an infinite stream
Stream<Integer> oddNumbers = Stream.iterate(1, n -> n+2);
Using Common
Terminal
Operations
count()
Determine the
number
elements in a
finite
stream
Signature
long count()
min() / max()
Pass a
custom comparator
and find the
smallest or largest
value in a
finite
stream
Signature
Optional<T> min(<? super T> comparator)
Optional<T> max(<? super T> comparator)
findAny() / findFirst()
Return an element of the stream unless the stream is empty (return an empty Optional)
Signature
Optional<T> findAny()
Optional<T> findFirst()
allMatch() / anyMatch() / noneMatch()
Search a stream and return information about how the stream pertains to the Predicate
Signature
boolean anyMatch(Predicate <? super T> predicate)
boolean allMatch(Predicate <? super T> predicate)
boolean noneMatch(Predicate <? super T> predicate)
forEach()
looping construct
Signature
void forEach(Consumer<? super T> action)
reduce()
Combine a stream into a single object
Signature
T reduce(T identity, BinaryOperator<T> accumulator)
Optional<T> reduce(BinaryOperator<T> accumulator)
<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
collect()
mutable reduction
Signatures
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R,R> combiner)
<R,A> R collect(Collector<? super T, A,R> collector)
Using Common
Intermediate
Operations
limit() and skip()
Stream<Integer> s = Stream.iterate(1, n -> n + 1);
s.skip(5).limit(2).forEach(System.out::print); // 67
map()
Create a one-to-one mapping from the elements in the stream to the elements of the next step in the stream
Signatures
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
distinct()
Return a Stream with duplicate values removed
Signatures
Stream<T> distinct()
flatMap()
Take each elements in the stream and make any elements it contains top-level elements in a single stream
Signatures
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
filter()
Return a
Stream
with elements that
match
a given expression
Signatures
Stream<T> filter(Predicate<? super T> predicate)
sorted()
Return a Stream with the elements sorted
Signatures
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
peek()
Perform a Stream operation without actually changing the stream
Signatures
Stream<T> peek(Consumer<? super T> action)
Putting Together the Pipeline
peek()
is useful for seeing how a stream pipeline works behind the secene
Printing a Stream
Working with Primitives
Using
Optional
with Primitive Streams
OptionalInt
Get as a primitive
getAsInt()
orElseGet()
parameter type
IntSupplier
Return type of
max()
OptionalInt
Return type of
sum()
int
Return type of
avg()
OptionalDouble
OptionalLong
orElseGet()
parameter type
LongSupplier
Return type of
max()
OptionalLong
Get as a primitive
getAsLong()
Return type of
sum()
long
Return type of
avg()
OptionalDouble
OptionalDouble
orElseGet()
parameter type
DoubleSupplier
Return type of
max()
OptionalDouble
Get as a primitive
getAsDouble()
Return type of
sum()
double
Return type of
avg()
OptionalDouble
Summarizing Statistics
Calculation about the stream
Average
Size
Maximum
Minimum
Number of values
Creating Primitive Streams
Types
IntStream
short
byte
int
char
LongStream
long
DoubleStream
double
float
Basic methods
generate()
iterate()
of()
range()
empty()
rangeClosed()
Learning the Functional Interfaces for Primitives
Functional Interfaces for
boolean
BooleanSupplier
boolean getAsBoolean()
Functional Interfaces for
double
,
int
, and
long
Working with Advanced Stream Pipeline Concepts
Chaining Optionals
Collecting Results
Collecting into Maps
Collectors
toMap(Function k, Function v, BinaryOperator m)
toMap(Function k, Function v)
toMap(Function k, Function v, BinaryOperator m, Supplier s)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
Map<String, Integer> result = ohMy.
collect
(Collectors.
toMap
(s -> s, String::length));
System.out.println(result);
Collecting Using Grouping, Partitioning, and Mapping
Create a map grouping by the specified
function
(with the optional type and optional downstream collector)
Collectors
groupingBy(Function f)
groupingBy(Function f, Collector dc)
groupingBy(Function f, Supplier s, Collector dc)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
Map<String, Integer> result = ohMy.
collect
(Collectors.
groupingBy
(String::length));
System.out.println(result);
Create a map grouping by the specified
predicate
with the optional further downstream collector
Collectors
partitioningBy(Predicate p)
partitioningBy(Predicate p, Collector dc)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
Map<String, Integer> result = ohMy.
collect
(Collectors.
partitioningBy
(String::length));
System.out.println(result);
Create a map using functions to map the keys, values, an optional merge function and an optional type
Colllectors
mapping(Function f, Collector dc)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
Map<Integer, Optional<Character>> result = ohMy.
collect
(Collectors.
groupingBy
(String::length, Collectors.mapping(s -> s.charAt(0), Collectors.minBy(Comparator.naturalOrder()));
System.out.println(result);
Collecting Using Basic Collectors
Create a
single String
(using CharSequence as a delimiter between elements if one is specified)
Collectors
joining()
joining(CharSequence cs)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
String result = ohMy.
collect
(Collectors.
joining
(", "));
System.out.println(result);
Calculate the average for our 3 core primitive types
Collectors
averagingInt(ToIntFunction f)
averagingDouble(ToDoubleFunction f)
averagingLong(ToLongFunction f)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
Double result = ohMy.
collect
(Collectors.
averagingInt
(String::length));
System.out.println(result);
Create a
Collection
of the specified type
Collectors
toCollection(Supplier s)
Example
Stream<String> ohMy = Stream.of("lions", "tigers", "bears");
TreeSet<String> result = ohMy.filter(s -> s.startsWith("t").
collect
(Collectors.
toCollection
(TreeSet::new));
System.out.println(result);
Linking Streams to the Underlying Data
Streams are
lazily evaluated