It’s hard to say whether .sorted().limit((long) N).toArray()
will get optimized in some cases (it’s implementation dependent but given Oracle’s current implementation, I wouldn’t expect it), but in this special case, the source stream is a stream of unknown size which makes optimizations even less likely.
If you want to be on the safe side, you may adapt this solution for getting the n maximum numbers of a stream efficiently. All you have to do is to reverse the order:
public static IntStream maxValuesDescending(IntStream source, int limit) {
TreeMap<Integer,Integer> m=new TreeMap<>(Comparator.reverseOrder());
source.forEachOrdered(new IntConsumer() {
int size, min=Integer.MIN_VALUE;
public void accept(int value) {
if(value<min) return;
m.merge(value, 1, Integer::sum);
if(size<limit) size++;
else m.compute(min=m.lastKey(), (k,count)->count==1? null: count-1);
}
});
if(m.size()==limit)// no duplicates
return m.keySet().stream().mapToInt(Integer::valueOf);
return m.entrySet().stream().flatMapToInt(e->{
int value = e.getKey(), count = e.getValue();
return count==1? IntStream.of(value): IntStream.range(0, count).map(i->value);
});
}
Then you can use it like
int[] arr = maxValuesDescending(in.lines().mapToInt(Integer::parseInt), N).toArray();
But you are not required to create an array as you can use arbitrary IntStream
operations on the result. This solution will hold at most N
values, even less if there are duplicates as it only holds distinct values and their count.