-
-
Save edalorzo/148c6e4f8f0c49d2d5f2 to your computer and use it in GitHub Desktop.
public static <T> Stream<T> concatenate(Stream<T>... streams) { | |
return Stream.of(streams).reduce(Stream.empty(), Stream::concat); | |
} | |
public static void main(String[] args) { | |
Stream<? extends CharSequence> res = concatenate( | |
Stream.of("One"), | |
Stream.of(new StringBuffer("Two")), | |
Stream.of(new StringBuilder("Three")) | |
); | |
res.forEach(System.out::println); | |
} |
What you say about the use of wildcards make sense when you want to bound a generic type to a specific bound like T extends Comparable or T extends Serializable.
But the use of ? extends T does not make sense at all in a generic method, since T will replace whatever type you pass already. In other words T is already as flexible as you can get.
My use of ? extends CharSequence was just an example, my code, without the use ? extends T works perfectly for the example you gave:
public static void main(String[] args) {
Stream<CharSequence> res = concatenate(
Stream.<CharSequence>of("One"),
Stream.of(new StringBuffer("Two")),
Stream.of(new StringBuilder("Three"))
);
res.forEach(System.out::println);
}
Ok it works but thanks to 'target type' of java 8. All of your Streams: "One", "Two", "Three" is exactly Stream< CharSequence >. Also first one might be written as Stream.of("One") and still it work but what if you have already declared Streams eg.:
Stream<String> f = Stream.of("One");
Stream<StringBuffer> s = Stream.of(new StringBuffer("Two"));
Stream<StringBuilder> t = Stream.of(new StringBuilder("Three"));
Stream<CharSequence> res = concatenate(f, s, t);
My version still work and simple T is not enough.
As you quote Michael Hixson in your original post probably the best implementation of concat would be Stream.of(s1, s2, s3, ...).flatMap(x -> x) or equal Stream.of(s1, s2, s3, ...).flatMap(identity())
Its not that <? extends T> is pointless. It is not! It gives you more flexibility:) Nonetheless maybe there is no point to write a function for concatenation maybe even Stream.concat() is useless cause of idiom: Stream.of(s1, s2, s3, ...).flatMap(identity()) but if you want to put it in method, signature should be precise <? extends T> :)
https://gist.github.com/kacperKant/e7852ef6a6ee4442fec9
Ok, there is one difference that when you put <? extends T> in method signature it leaves client code clearer. Client do not have to specify long <? extends Something> instead simple < Something >. You may say there is no difference but you can treat Stream<? extends Something> only as it contains < Something > so why we shouldn't return it in the first place?
Additionally I vote for your answer on stackoverflow cause it is great. I am writing post on linkedin and I'll put link to your post of the history of Stream.concat method in api. Hope it is ok:)