Hello! Still from the practical point of view it would be really helpful to have instance methods like `Stream.append(T... elements)` and `Stream.prepend(T... elements)` (default implementation may utilize `concat`). Very often it's necessary to add one or two special elements to the stream, and using the `concat` makes code very ugly.
C.f.: list.stream().filter(...).map(...).append(specialElement).collect(toList()); v.s.: Stream.concat(list.stream().filter(...).map(...), Stream.of(specialElement)).collect(toList()); Currently I prefer this (unless I can use third-party libraries which provide `append`): List<T> result = list.stream().filter(...).map(...).collect(toList()); // toCollection(ArrayList::new) for purists result.add(specialElement); With best regards, Tagir Valeev. On Thu, Oct 11, 2018 at 11:11 PM Brian Goetz <brian.go...@oracle.com> wrote: > > It would surely be convenient; I've wished for this a few times. But, > there's a reason for this choice, and its not just laziness; > contravariant type variables have some pretty scary challenges. See, for > example, this paper: > > http://www.cis.upenn.edu/~bcpierce/papers/variance.pdf > > in which it is shown that contravariance is one of the ingredients in a > witches brew that leads to undecideability of type checking. > > > > On 10/11/2018 12:06 AM, James Roper wrote: > > With the work I'm doing at the moment at creating a Reactive Streams > > equivalent to java.util.stream, I've often wondered why Stream.concat is a > > static method, rather than an instance method concating the given stream > > onto this. But I think the reason has just dawned on me, and I wanted to > > confirm that I'm correct. > > > > Java doesn't support contravariant type variables - it does for type > > declarations, but not type variables. > > > > To put more concretely, if I had a Stream<Integer>, and I wanted to concat > > a Stream<Number>, this is a valid thing to do, the resulting stream would > > be Stream<Number>. But doing that with an instance method would require > > something like this: > > > > public <S super T> Stream<S> concat(Stream<? extends S> b); > > > > Which is not supported (specifically, <S super T> type variable declaration > > is not supported). In contrast, what we have in the actual API: > > > > public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends > > T> b); > > > > does allow me to concat a Stream<Integer> and Stream<Number> with a > > resulting type of Stream<Number>. > > > > Is this right, or are there other reasons? Also, is there any possibility > > that Java might support contravariance in type variables in future? My > > reason for wanting it is to provide the following method for reactive > > streams: > > > > public <S super T> Publisher<S> onErrorResumeWith(Function<? super > > Throwable, ? extends Publisher<? extends S>> f); > > > > The intent of this method is when a stream encounters an error, the passed > > function is invoked with the error, and that function returns a publisher > > that gets concated to the current stream instead of the error being > > emitted. This could possibly be implemented with a static method: > > > > public static <T> Publisher<T> onErrorResumeWith(Publisher<? extends T> a, > > Function<? super Throwable, ? extends Publisher<? extends T> f); > > > > But unlike concat, this method feels and reads much better as an instance > > method, as a static method it's a little confusing. > > > > Regards, > > > > James > > >