Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there no Instance-level Stream.concat method in Java?

I know that Stream.concat exists (doc) to concatenate two streams. However, I have run into cases where I need to add "a few more" items to an existing stream, and then continue processing on it. In such a situation, I would have expected to be able to chain together methods like:

getStream(someArg)
  .map(Arg::getFoo)
  .concat(someOtherStreamOfFoos) // Or append, or...
  .map(...)

However, no such instance-level chainable append/concat method exists.

This isn't a question asking for solutions to this problem, or more elegant approaches (although I would of course be grateful for any other viewpoints!). Rather, I'm asking about the design factors that led to this decision. The Stream interface was, I trust, designed by some extremely smart people who are aware of the Principle of Least Astonishment - so, I must assume that their decision to omit this (to me) intuitively-obvious method signifies either that the method is an antipattern, or that it is not possible due to some technical limitation. I'd love to know the reason.

like image 714
scubbo Avatar asked Apr 02 '18 17:04

scubbo


People also ask

How do you concatenate streams in Java?

concat() in Java. Stream. concat() method creates a concatenated stream in which the elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel.

What are streams in Java 8?

Introduced in Java 8, the Stream API is used to process collections of objects. A stream is a sequence of objects that supports various methods which can be pipelined to produce the desired result. A stream is not a data structure instead it takes input from the Collections, Arrays or I/O channels.


1 Answers

I can give you one reason it wouldn't have worked.

Stream.concat is defined as

static <T> Stream<T> concat(Stream<? extends T> a,
                            Stream<? extends T> b)

You can concat a Stream<HashMap> and Stream<Map> into a Stream<Map>, or even concat a Stream<HashMap> and a Stream<TreeMap> into a Stream<Map>. To do that with an instance method, you would need to be able to declare a type parameter like <U super T>, which Java doesn't allow.

// It'd look kind of like this, if Java allowed it.
public <U super T> Stream<U> concat(Stream<? extends U> other)

Java only allows upper-bounded type parameters, not lower-bounded.

Concatenating a Stream<Something> and a Stream<SomethingElse> might seem unusual, but type inference often produces type parameters too specific to work with an instance method. For example,

Stream.concat(Stream.of(dog), animalStream)

which would require an explicit type parameter if written as

Stream.<Animal>of(dog).concat(animalStream)
like image 183
user2357112 supports Monica Avatar answered Oct 07 '22 11:10

user2357112 supports Monica