Faster, Lazy, extended (& powerful) JDK Collections

John McClean
3 min readNov 7, 2016

--

cyclops-react has extended JDK Collection types, I wrote an introductory overview on medium last year.

Extended collections offer features such as mapping, filtering, flatMapping, grouping, sliding windows, zipping, extracting combinations and permutations and much more.

Eager execution

The extensions packaged with cyclops-react, all act eagerly. What that means is that in the chain of operations below the List will be traversed twice, once for the map operation and once during filtering.

The reason for this is that the above code is really syntax sugar for a series of Stream operations

Which makes using large numbers of operations with large datasets particularly inefficient. It would be nice if we could write the same code but traverse the List only once. We did implement a Lazy version of the cyclops-react extended collections, but as they were backed by traverse once Streams we ran in to some problems. If a List was lazily transformed, stored and then transformed in two different ways, accessing the data potentially triggers two different terminal operations on the same Stream — causing a nasty RuntimeException. So the Stream backed extended Collections in cyclops-react had an additional suite of eagerly executed operators.

Other Stream types don’t suffer from this traverse once limitation — enter cyclops-reactor, the cyclops integration library for Pivotal’s Reactor project.

cyclops-reactor link : https://github.com/aol/cyclops/tree/master/cyclops-reactor

Lazy Lists backed by Flux

Flux is the re-traversable stream implementation in Pivotal’s Reactor library. Because it is re-traversable, we can create extended collections that have lazy operations and can more efficiently process the data set (looping just once through the list no matter how many additional operations are teed up).

cyclops-reactor’s LazyListX extends ListX

And is syntax sugar for something more like this

A ListX facade is presented to the user, and the List materialized on first access.

Extended functionality

The ListX interface provides a large range of advanced operators, there are some examples below.

zipping and sliding windows

The zipping operator allows a Lazy Collection to be combined with another collection or reactive-streams publisher in a user defined manner. In the example below, we combine the pair-wise elements of two Lists into a String.

The sliding operator allows us to create a sliding window over the data in our lazy collection (and there are many other grouping options too).

onEmptySwitch allows us to specify a default List if ours is empty.

for-comprehensions

For comprehensions allow us to perform a cartesian production operation on two or more collections (and other data types too). That is to join (and then optionally filter) every combination of elements across the supplied (or generated) collections.

Data emission

Lazy collections have number of handy operators that allow data to be emitted from a collection in a controlled way, for example schedule allows us to schedule emission via a cron expression, with a fixed rate or fixed delay. onePer emits one element every specified time period (much like fixed rate).

Lazy Extended Collections Available

Standard JDK collections and their Javadoc links!

1. LazyListX
2. LazyDequeX
3. LazyQueueX
4. LazySetX
5. LazySortedX

Persistent collections

Persistent collections and their Javadoc links!

1. LazyPStackX — A persistent LinkedList
2. LazyPVectorX — A persistent Vector — an ArrayList analogue
3. LazyPQueueX — A persistent Queue
4. LazyPSetX — A persistent Set
5. LazyPOrderedSetX — A persistent OrderedSet
6. LazyPBagX — A persistent Bag

--

--

John McClean

Architecture @ Verizon Media. Maintainer of Cyclops. Twitter @johnmcclean_ie