Avoid Stream where possible in interfaces.
Streams may
* be finite or infinite
* be sequential or parallel
* be ordered or non-ordered
* need closing or not
Neither the implementors of an interface nor the clients of the interface can know which of these characteristics should (not) apply or which they need to guard against.
Choosing the most flexible return type in an interface just means that clients have the full burden of guarding against all possibilities. It is generally much more useful in an interface to restrict the returned datatype so that implementors know what assumptions they can rely one (for the same reason returning Collection
itself is not very useful in most cases, it is more useful to return List, Set, Iterable, InputStream
to indicate rights and duties of clients when consuming the data).
And when you need to change the characteristics of the returned data, change the interface,b break your clients intentionally, so that they can update their algorithms to the changed situation.
That's much more useful than to say: "My method returns a Stream, so now I can return an infinite stream instead of a finite one, and the client code still compiles, how wonderful!". It is not wonderful, it is a horrible source of bugs to do that. Client code should NOT continue to compile with such drastic changes, so using datatypes that are explicit about finity, parallelity, orderedness and duty to close()
is a much better choice.
Think like this: If remaining flexible was so great, then all interfaces that in Java7 return List
or Set
or Queue
would be returning Iterable
instead, to remain flexible in what datatype to actually return. But this is not what most interfaces do returning a Collection instead tells clients they can safely rely on a size() method, and returning a Set means they can safely rely on non-duplication, as an example. Being specific and restrictive in interfaces is not a sin, it is a virtue.