Stream API in Java
In Java 8, every class which implements the java.util.Collection interface has a stream method which allows you to convert its instances intoStream objects.
- Technically: typed interface
- Extends: BaseStream
- Also has: IntStream, LongStream, DoubleStream based on primitive data types int, long and double
Properties:
Does not hold data
- pulls data from given source
- connects to source, consumes the data and processes it
Does not modify data
- because data is processed in parallel with no visibility issues
- not enforced by compiler, merely a contract
Source may be unbounded
- not finite meaning number of elements produced by the source is unknown at build time
Patterns for building
Stream.empty(); // an empty streamStream.of("one"); // singleton streamStream.of("one", "two", "three"); // stream with multiple elementsStream.generate(() -> "one"); // constant stream using SupplierMade usingStream.iterate("+", s -> s + "+"); // a growing streamUnaryOperatorwhich takes an element and returns another of the same type.iteratetakes the current element of the stream as the first argument, gets the result from theUnaryOperatorof the second argument and uses that as the next element in the stream.ThreadLocalRandom.current().ints(); // a random streamIntStream stream = "hello".chars();charsmethod returns an int stream based on the letters of the characters.IntStream stream = "hello".chars();charsmethod returns an int stream based on the letters of the characters. -The Pattern class implements the regular expression engine in JDK. It provides a Pattern object by calling theStream<String> words = Pattern.compile().splitAsStream(something); // stream on a regular expressioncompilestatic method. -Stream<String> lines = Files.lines(path); // stream on the lines of a text file
Terminal v/s Intermediate operation
A terminal operation must be called to trigger processing on the stream. Without it, no data is consumed, processed or returned.
Example
forEach v/s peek. We cannot substitute forEach calls with peek calls as peek is an intermediate operation created for debugging purposes.
Differentiating
- Javadoc specifies terminal or intermediate
- A call that returns Stream -> intermediate. A call that returns something else or void -> terminal
Functions
- map
- filter
- peek
- forEach
- skip
- limit
- Match Reductions returning boolean -> anyMatch (any element), allMatch (all elements), noneMatch ^^^ may not evaluate predicate for all elements -> short circuiting terminal operations
- Find Reductions -> findFirst (returns any if the stream is unordered -> built on a set etc), findAny
Reduce Reductions
1. Provided the list has only positive numbers (since the identity for max is 0 over a positive range)
int maxNum =
list.stream()
.reduce(0, (p1, p2) -> Integer.max(p1, p2));
2. If identity element is not provided, Optional is returned -> result of the reduction on an empty stream is not defined
Optional<Integer> maxNum =
list.stream()
.reduce((p1, p2) -> Integer.max(p1, p2));