Collect successive pairs from a stream
java, java-8, java-stream
Solution
There is built-in support for this in the JEP 461: Stream Gatherers Java 22 preview language feature:
Stream.of(0, 1, 2, 3, 4)
.gather(Gatherers.windowSliding(2))
.map(list -> new Pair(list.get(0), list.get(1)))
.toList();
This uses the new `Stream.gather` method with the new built-in `Gatherers.windowSliding` gatherer to convert the initial `Stream<Integer>` (`[0, 1, 2, 3, 4]`) to a pairwise `Stream<List<Integer>>` (`[[0, 1], [1, 2], [2, 3], [3, 4]]`). Each of these lists is then transformed to a `Pair` using the existing `Stream.map` method.
Javadocs
`Gatherer`:
An intermediate operation that transforms a stream of input elements into a stream of output elements, optionally applying a final action when the end of the upstream is reached. […]
[…]
There are many examples of gathering operations, including but not limited to: grouping elements into batches (windowing functions); de-duplicating consecutively similar elements; incremental accumulation functions (prefix scan); incremental reordering functions, etc. The class `Gatherers` provides implementations of common gathering operations.
`Stream.gather`:
Returns a stream consisting of the results of applying the given gatherer to the elements of this stream.
`Gatherers.windowSliding`
Returns a Gatherer that gathers elements into windows -- encounter-ordered groups of elements -- of a given size, where each subsequent window includes all elements of the previous window except for the least recent, and adds the next element in the stream. […]
Example:
// will contain: [[1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8]]
List<List<Integer>> windows2 =
Stream.of(1,2,3,4,5,6,7,8).gather(Gatherers.windowSliding(2)).toList();
// will contain: [[1, 2, 3, 4, 5, 6], [2, 3, 4, 5, 6, 7], [3, 4, 5, 6, 7, 8]]
List<List<Integer>> windows6 =
Stream.of(1,2,3,4,5,6,7,8).gather(Gatherers.windowSliding(6)).toList();
Problem
Given an object or primitive stream such as `{ 0, 1, 2, 3, 4 }`, how can I most elegantly transform it into given form (assuming, of course, I've defined class `Pair`)? `{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }`
Related problems
- How to ensure order of processing in java8 streams?
- Is .collect guaranteed to be ordered on parallel streams?
- How to use Java 8 streams to find all values preceding a larger value?
- Is it possible to get next element in the Stream?
- Efficient way to divide a list into lists of n size
- Idiom for pairwise iteration through a sorted collection