【发布时间】:2011-12-14 05:59:00
【问题描述】:
相关问题:
- Java PriorityQueue with fixed size
- How do I use a PriorityQueue?
- get indexes of n smallest elements in an array
- Scala: Is there a way to use PriorityQueue like I would in Java?
我有一个非常大的数据集(超过 500 万个项目),我需要从中获取 N 个最大的个项目。最自然的方法是使用堆/优先队列只存储前 N 个项目。 JVM(Scala/Java)的优先级队列有几个很好的实现,分别是:
前 2 个很好,但它们存储了所有项目,在我的情况下,这会产生严重的内存开销。第三个(Lucene 实现)没有这样的缺点,但正如我从文档中看到的那样,它也不支持自定义比较器,这对我来说毫无用处。
所以,我的问题是:是否有 PriorityQueue 实现具有固定容量和自定义比较器?
UPD。最后我根据彼得的回答创建了自己的实现:
public class FixedSizePriorityQueue<E> extends TreeSet<E> {
private int elementsLeft;
public FixedSizePriorityQueue(int maxSize) {
super(new NaturalComparator());
this.elementsLeft = maxSize;
}
public FixedSizePriorityQueue(int maxSize, Comparator<E> comparator) {
super(comparator);
this.elementsLeft = maxSize;
}
/**
* @return true if element was added, false otherwise
* */
@Override
public boolean add(E e) {
if (elementsLeft == 0 && size() == 0) {
// max size was initiated to zero => just return false
return false;
} else if (elementsLeft > 0) {
// queue isn't full => add element and decrement elementsLeft
boolean added = super.add(e);
if (added) {
elementsLeft--;
}
return added;
} else {
// there is already 1 or more elements => compare to the least
int compared = super.comparator().compare(e, this.first());
if (compared == 1) {
// new element is larger than the least in queue => pull the least and add new one to queue
pollFirst();
super.add(e);
return true;
} else {
// new element is less than the least in queue => return false
return false;
}
}
}
}
(其中NaturalComparator 取自this 问题)
【问题讨论】:
-
我对你的实现的拙见:1)你真的需要扩展TreeSet吗? “FixedSizePriorityQueue 是一个 TreeSet”听起来不太好,我会让该集合成为一个成员。 2)您实际上并不需要通过使 elementsLeft 成为非最终变量来为您的类添加状态。 3) 你确定 add 方法总是返回正确的值吗? 4) 防止无效或非法参数是一种好习惯。
-
@Murat:感谢您的建议。随时在此处发布您改进的实现作为答案。
-
不客气,谢谢:) 将其发布为答案。
-
如果队列已满并且您添加了一个已经存在于其中的元素(并且不是将被轮询的最后一个元素),您的解决方案将错误地离开
elementsLeft == 0,而在这种情况下它必须变成 1。 -
其实队列满的时候应该先添加元素并查看结果。如果为假,则不必投票。
标签: java scala heap priority-queue