Can we somehow split stream into substreams with no more than N elements in Java? For example
Stream<Integer> s = Stream.of(1,2,3,4,5);
Stream<Stream<Integer>> separated = split(s, 2);
// after that separated should contain stream(1,2), stream(3,4), stream(5)
splitting by two streams solution is correct only for 2 streams, the same for N streams will be very ugly and write-only.
You can't split a Stream
into 2 or more Streas
s easily and directly. The only way the procedural one consisting of collecting the elements to the List
by the couples and mapping them back to Stream
again:
Stream<Integer> s = Stream.of(1,2,3,4,5);
List<Integer> list = s.collect(Collectors.toList());
int size = list.size();
List<List<Integer>> temp = new ArrayList<>();
List<Integer> temp2 = new ArrayList<>();
int index = 0;
for (int i=0; i<size; i++) {
temp2.add(list.get(i));
if (i%2!=0) {
temp.add(temp2);
temp2 = new ArrayList<>();
}
if (i == size - 1) {
temp.add(temp2);
}
}
Stream<Stream<Integer>> stream = temp.stream().map(i -> i.stream());
As you see it's a really long way an not worth. Wouldn't be better to store the pairs in the List
rather than Stream
? The java-stream API is not used for data storage but their processing.
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.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With