Given a stream such as { 0, 1, 2, 3, 4 }
,
how can I most elegantly transform it into given form:
{ new Pair(0, 1), new Pair(1, 2), new Pair(2, 3), new Pair(3, 4) }
(assuming, of course, I've defined class Pair)?
Edit: This isn't strictly about ints or primitive streams. The answer should be general for a stream of any type.
The collect() method in Stream API collects all objects from a stream object and stored in the type of collection. The user has to provide what type of collection the results can be stored. We specify the collection type using the Collectors Enum.
Java Stream forEach() method is used to iterate over all the elements of the given Stream and to perform an Consumer action on each element of the Stream.
You obtain a stream from a collection by calling the stream() method of the given collection. Here is an example of obtaining a stream from a collection: List<String> items = new ArrayList<String>(); items.
The Java 8 streams library is primarily geared toward splitting streams into smaller chunks for parallel processing, so stateful pipeline stages are quite limited, and doing things like getting the index of the current stream element and accessing adjacent stream elements are not supported.
A typical way to solve these problems, with some limitations, of course, is to drive the stream by indexes and rely on having the values being processed in some random-access data structure like an ArrayList from which the elements can be retrieved. If the values were in arrayList
, one could generate the pairs as requested by doing something like this:
IntStream.range(1, arrayList.size()) .mapToObj(i -> new Pair(arrayList.get(i-1), arrayList.get(i))) .forEach(System.out::println);
Of course the limitation is that the input cannot be an infinite stream. This pipeline can be run in parallel, though.
My StreamEx library which extends standard streams provides a pairMap
method for all stream types. For primitive streams it does not change the stream type, but can be used to make some calculations. Most common usage is to calculate differences:
int[] pairwiseDiffs = IntStreamEx.of(input).pairMap((a, b) -> (b-a)).toArray();
For object stream you can create any other object type. My library does not provide any new user-visible data structures like Pair
(that's the part of library concept). However if you have your own Pair
class and want to use it, you can do the following:
Stream<Pair> pairs = IntStreamEx.of(input).boxed().pairMap(Pair::new);
Or if you already have some Stream
:
Stream<Pair> pairs = StreamEx.of(stream).pairMap(Pair::new);
This functionality is implemented using custom spliterator. It has quite low overhead and can parallelize nicely. Of course it works with any stream source, not just random access list/array like many other solutions. In many tests it performs really well. Here's a JMH benchmark where we find all input values preceding a larger value using different approaches (see this question).
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