-
Notifications
You must be signed in to change notification settings - Fork 4
Streams and Lambdas
Java 8 added Streams to the standard library and lambda expressions to the language. These are directly supported by Javimmutable collections. Streams allow you to operate on all elements of a collection either serially or in parallel. Javimmutable supports Streams through a new interface named IStreamable
. This interface defines two methods for creating Streams:
Stream stream();
Stream parallelStream();
The stream()
method returns a Stream for processing the collection in a single thread. The parallelStream()
method returns a Stream for processing the collection using multiple threads. (Using parallelStream()
is similar to using stream().parallel()
).
All collections implement the IStreamable
interface. In addition several collections have view methods that return IStreamable
objects for operating on a slice of the collection. For example, IMap
defines these view methods:
-
keys()
returns a view for operating on just the keys in the map -
values()
returns a view for operating on just the values in the map
Other collections define these view methods as well. IMultiset
defines its own view methods:
-
entries()
returns a view for operating onIMapEntry
objects containing each value plus its count -
ocurrences()
returns a view for operating on all values in the multiset with each value appearing its count times in the stream
Streams can be used to build collections efficiently using the Collector
implementations defined in ICollectors
. See [Collections Overview] for details.
IList<String> source = ILists.of("axle", "wheel", "apple", "wall");
ISet<String> copied = source.stream().collect(ICollectors.toSet());
// copied now contains "apple", "axle", "wall", and "wheel"
IStreamable
extends Iterable
so it inherits the helper methods from that interface. It also provides some of its own. These operate on all of the values of the collection without using a stream.
The forEach()
method passes every item in the collection to a provided lambda. The forEachThrows()
does the same but accepts that lambda that can throw a checked exception.
The indexedForEach()
method passes every item in the collection along with its index to a provided lambda. The provided index starts at zero and incements by one for each item. The indexedForEachThrows()
does the same but accepts that lambda that can throw a checked exception.
Sometimes you need to process all elements to produce a single result. For example you may want to compute the sum of a list of integers. The IStreamable
interface provides a method for doing so.
The reduce()
method accepts a starting value and a lambda that accepts the current value plus an element from the collection. The lambda is invoked once for each element. The first call to the lambda receives the initial value and the first element. All other calls receive the result of the previous call and an element. The result of the reduce()
call is the final value returned by the lambda.
IList<Integer> values = ILists.of(1, 2, 3, 4, 5, 6, 7, 8);
assertEquals(36, (int)values.reduce(0, (s,x) -> s + x)); // 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
assertEquals(-18, (int)values.reduce(18, (s,x) -> s - x)); // 18 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8
assertEquals(16, (int)values.reduce(0, (s,x) -> s + (x / 2))); // 0 + 0 + 1 + 1 + 2 + 2 + 3 + 3 + 4
An equivalent method, reduceThrows
is provided that accepts a function that can throw a checked exception.