The JEP 485: Stream Gatherers Java 24 language feature (available as a preview language feature since Java 22) adds built-in support for partitioning a stream into lists of a given size. These lists could then be mapped into streams.
// A stream containing 2 (or less) element streams: [[1, 2], [3, 4], [5]] Stream<Stream<Integer>> separated = Stream.of(1, 2, 3, 4, 5) .gather(Gatherers.windowFixed(2)) .map(Collection::stream);
This uses the new Stream.gather method with the new built-in Gatherers.windowFixed gatherer to convert the initial Stream<T> to a Stream<List<T>>. This is then converted to a Stream<Stream<T>> using Stream.map with Collection::stream as the mapping function.
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.windowFixed
Returns a Gatherer that gathers elements into windows -- encounter-ordered groups of elements -- of a fixed size. If the stream is empty then no window will be produced. The last window may contain fewer elements than the supplied window size.
Example:
// will contain: [[1, 2, 3], [4, 5, 6], [7, 8]] List<List<Integer>> windows = Stream.of(1,2,3,4,5,6,7,8).gather(Gatherers.windowFixed(3)).toList();