Is there is a good way to add a new value to existing Stream
? All I can imagine is something like this:
public <T> Stream<T> addToStream(Stream<T> stream, T elem ) { List<T> result = stream.collect(Collectors.toList()); result.add(elem); return result.stream(); }
But I'm looking for something more concise that I can use in lambda expression without verbosity.
Another question appeared when I tried to implement PECS principle:
public <T> Stream<? super T> addToStream(Stream<? super T> stream, T elem ) { List<? super T> result = stream.collect(Collectors.toList()); //error result.add(elem); return result.stream(); }
Seems like wildcard doesn't work with Stream.collect
and I'm wondering why. Thanks in advance.
This operation is not fully supported by Stream API because essentially Streams are not collections and do not recognize the concept of indexes. So, in order to do this, we need to convert the Stream to a list, then insert the element, and finally, get a Stream from that new list.
There are two methods to add elements to the list. add(E e): appends the element at the end of the list. Since List supports Generics, the type of elements that can be added is determined when the list is created. add(int index, E element): inserts the element at the given index.
The question belies an incorrect assumption: that streams actually contain their data. They do not; streams are not data structures, they are a means for specifying bulk operations across a variety of data sources.
There are combinators for combining two streams into one, such as Stream.concat
, and factories for creating streams from a set of known elements (Stream.of
) or from collections (Collection.stream
). So you can combine these if you want to produce a new stream that is the concatenation of the stream you have in hand, along with a new stream describing the new elements.
The problem in your PECS example is that you've got three occurrences of ? super T
, and you are assuming they describe the same type, but they do not. Each occurrence of a wildcard corresponds to a unique capture, which isn't what you want; you need to give that type variable a name so the compiler knows that the type of the list and the type of the input stream are the same. (Also, don't materialize a collection; that's expensive, and potentially non-terminating if the stream is not finite. Just use concat.) So the answer is: you just got the generics wrong. Here's one way to do it:
public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) { return Stream.concat(stream, Stream.of(element)); }
You confused yourself with PECS because you were thinking about "inserting" into the stream, when in fact you're consuming from it.
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