Just poll()
the queue if its least element is less than (in your case, has worse rating than) the current element.
static <V extends Comparable<? super V>>
PriorityQueue<V> nbest(int n, Iterable<V> valueGenerator) {
PriorityQueue<V> values = new PriorityQueue<V>();
for (V value : valueGenerator) {
if (values.size() == n && value.compareTo(values.peek()) > 0)
values.poll(); // remove least element, current is better
if (values.size() < n) // we removed one or haven't filled up, so add
values.add(value);
}
return values;
}
This assumes that you have some sort of combination class that implements Comparable
that compares combinations on their rating.
Edit: Just to clarify, the Iterable
in my example doesn't need to be pre-populated. For example, here's an Iterable<Integer>
that will give you all natural numbers an int
can represent:
Iterable<Integer> naturals = new Iterable<Integer>() {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
int current = 0;
@Override
public boolean hasNext() {
return current >= 0;
}
@Override
public Integer next() {
return current++;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
Memory consumption is very modest, as you can see - for over 2 billion values, you need two objects (the Iterable
and the Iterator
) plus one int
.
You can of course rather easily adapt my code so it doesn't use an Iterable
- I just used it because it's an elegant way to represent a sequence (also, I've been doing too much Python and C# ☺).