Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding new value to existing Stream

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.

like image 316
Dmytro Avatar asked Feb 28 '15 19:02

Dmytro


People also ask

Can we add in stream Java?

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.

How do I add elements to an existing list in Java?

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.


1 Answers

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.

like image 157
Brian Goetz Avatar answered Sep 25 '22 01:09

Brian Goetz