Chapter 4: Functional Programming Flashcards
Supplier
When we want to generate or supply values with no input.
Method name is get()
Consumer + BiConsumer
Do something with a parameter or two parameters but have no input.
Method name is accept.
Predicate + BiPredicate
Returns a boolean value (can be used in filtering and matching.
method name is test()
Can join predicates using .and()
Can negate predicate using .negate()
Function + BiFunction
Takes one parameter & returns another type. (Similar for Bifunction but taking two params and returning a type).
Method name is apply
UnaryOperator + BinaryOperator
Transforms one or two values into a single one of the same type.
Method name is apply
Optional.ofNullable
Returns optional.empty() if value is null
Optional.orElse()
.orElse returns something else of SAME type
.orElseGet takes a supplier to return something of the same type
.orElseThrow takes a supplier to throw an exception
Stream min/max
Pass in a comparator, returns optional as no min/max could be found
Stream findAny
Finds any value (faster than findFirst if you’re using parallelStreams)
Stream reduce
Combines a stream into a single object. T reduce (T identity, BinaryOperator accumulator) Identity is the initial state/what is returned on empty stream and accumulator specifies how to merge with the next value.
T reduce (BinaryOperator accumulator) We can omit the identity if we want, but then it will return optional
<u> U reduce (identity, BiFunction, BinaryOperator)
Can be used for parralel streams
Or if we want to apply a function to an object in our stream before accumulating them.</u>
Stream collect
R collect (Supplier, BiConsumer, BiConsumer)
Supplier supplies a new object or collection which will store the value. This is a single container.
BiConsumer accumulates values in each container.
Other BiConsumer merges the results across all the containers
Note can also use a Collector to collect values.
Stream intermediate operations
limit(int max size) + skip(int n). Watch out for where .limit is used, x number of items needs to have passed that point.
flatMap(), flattens a stream of collections to a stream of objects. E.g. Stream> –> Stream
sorted() either uses natural order, or you can pass in a comparator
peek() takes in a consumer which allows us to. perform a Stream operation without changing the stream. peek musn’t change the state of the Stream or there will be an error! This can be used for printing out values in the stream, for example.
Generating a new Stream
Stream.generate(Supplier) or Stream.iteratore(start, function)
we need to limit this otherwise it will be an infinite stream..
Primitive streams
IntStream, LongStream, DoubleStream.
Creating a new stream using IntStream.empty() or .of(…)
IntStream.range(lower, upper) generates values, upper is exclusive
IntStream.rangeClosed(lower, upper) generates values, upper is inclusive.
Mapping between primitive types of Stream
For each type of primitive stream you can map to another using the mapToX() method. E.g. mapToDouble converts to DoubleStream or mapToObj() maps to a standard stream. For each of these you need to provide a mapping function to indicate how to map to that data type. If you’re just mapping to itself e.g. using map() then you need a _UnaryOperator e.g. DoubleUnaryOperator. Otherwise you need a _To_Function e.g. LongToIntFunction. If you’re mapping to normal stream you need a _Function e.g. DoubleFunction. Note you may need to cast if you’re going from a larger to a smaller type so it will compile!
Primitive optionals
Optional_ e.g. OptionalDouble. You call .getAsDouble instead of get. orElseGet() takes a DoubleSupplier instead of a standard supplier.
.avg() will return Optional_. Note that IntStream avg() will return OptionalDouble!
Summarising statistics
.summaryStatistics() returns _SummaryStatics() e.g. IntSummaryStatistics(). Which can give you the max, min and count
Functional Interfaces for primatives
Suppliers methods are getAsX() e.g. BooleanSupplier getAsBoolean.
Operators e.g. DoubleBinaryOperator methods as applyAsDouble.
Lazy evaluation of Streams
Streams are lazily evaluated, so don’t get evaluated until there is a terminal operation. So if you add something to the underlying data which is in the stream (e.g. add to a list) it will be evaluated by the stream at the terminal operation
Chaining optionals
If you want to convert from one optional type to another, you need to use flatmap to ensure the optional stays at the top level (otherwise you may end up with Optional>.
Collectors partitioningBy
Takes in a Predicate and returns Map>.
If we don’t want the values collected to a List, we can pass in a Collector to collect it into another collection
Collectors toMap
toMap(Function for key, Function for value). Specifies how you want to map your keys and values. If we try to Map duplicate Keys we will throw an IllegalStateException. There is also an overload where you can pass in a merge function as a 3rd parameter, which will allow you to indicate how to merge values if there are any duplicates.
Iterator in streams
Needs to be .iterate(1, x, ++x) otherwise you will get an infinite iteration of 1’s if it is (1, x, x++)