Let me start by making the general point that the Java language specification places few restrictions on how streams are implemented. So it's really not too meaningful to ask about the performance of Java streams: it will vary significantly between implementations.
Also note that Stream
is an interface. You can create your own class that implements Stream
to have any performance or special behaviour on sorted
that you want. So really asking about the performance of Stream
makes no sense even within the context of one implementation. The OpenJDK implementation has lots of classes that implement the Stream
interface.
Having said that, if we look at the OpenJDK implementation, sorting of streams ends up in SortedOps
class (see source here) you will find that the sorting methods end up returning extensions of stateful operations. For example:
private static final class OfInt extends IntPipeline.StatefulOp<Integer>
These methods check if the upstream is already sorted in which case they just pass it to the downstream. They also have special exceptions for sized streams (i.e. upstream) which preallocate the arrays that they end up sorting which will improve efficiency (over a SpinedBuffer
that they use for unknown size streams). But whenever the upstream is not already sorted they accept all items, then sort them and then send to the accept
method of the downstream instance.
So the conclusion from this is that the OpenJDK sorted
implementation collects all items, then sorts, then sends downstream. In some cases this will be wasting resources when the downstream will then discard some elements. You are free to implement your own specialised sort operation that is more efficient than this for special cases. Probably the most straightforward way is to implement a Collector
that keeps a list of the n largest or smallest items in the stream. Your operation might then look something like:
.collect(new CollectNthLargest(4)).stream()
To replace
.sorted().limit(4)