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) }`

Original source

Related problems