Adding a new value to an existing stream

Is there a good way to add a new value to an 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 a lambda expression without verbosity.

Another question came up when I tried to implement the 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(); } 

The wildcard seems to not work with Stream.collect , and I wonder why. Thanks in advance.

+72
java wildcard java-8
Feb 28 '15 at 19:21
source share
5 answers

The question contradicts the wrong assumption: threads actually contain their data. They are not; streams are not data structures; they are a means for defining mass operations in various data sources.

Combinators combine two streams into one, for example Stream.concat , and factories for creating streams from a set of known elements ( Stream.of ) or from collections ( Collection.stream ). So you can combine them if you want to create a new stream, which is a concatenation of the stream that you have, along with a new stream that describes the new elements.

The problem in your PECS example is that you have three occurrences ? super T ? super T , and you assume that they describe the same type, but they do not. Each occurrence of a wildcard corresponds to a unique capture, which is not what you want; you need to specify a variable of type name so that the compiler knows that the type of the list and the type of the input stream are the same. (Also, don’t materialize in the collection, it is expensive and potentially not ending if the stream is not finite. Just use concat.) So, the answer is: you just got the generics wrong. Here is one way to do this:

 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 β€œpasting” into a stream when you actually consume it.

+89
Feb 28 '15 at 20:11
source share

What about

 return Stream.concat(stream, Stream.of(elem)); 

this assumes the source stream is finite. If this is not the case, you can execute them in reverse order.

+30
Feb 28 '15 at 19:26
source share

The StreamEx library has the corresponding #prepend() and #append() . Here is an example of how to use them:

 StreamEx.of("second").prepend("first").append("third").forEach(System.out::println); 

The output is as follows:

 first second third 
+1
Jun 01 '18 at 11:00
source share
  1. Convert stream to list
  2. Add New Item
  3. Convert back to stream
0
Jun 19 '19 at 12:06 on
source share

The best way is to use flatMap as follows:

 public <T> Stream<T> appendToStream(Stream<T> stream, T element) { return stream.flatMap(e -> Stream.of(e, element)); } 

This works with the source stream, so it could just be another intermediate operation in the stream, for example:

  stream.flatMap(e -> Stream.of(e, element)) .map(...) .filter(...) .collect(Collectors.toList()); 
0
Aug 19 '19 at 21:16
source share



All Articles