具有固定大小的 Java PriorityQueue
我正在计算算法的大量可能的结果组合。为了对这些组合进行排序,我用双值对它们进行评级并将它们存储在 PriorityQueue 中。目前,该队列中有大约 200k 个项目,这非常占用内存。实际上,我只需要说出列表中所有项目中最好的 1000 或 100 个。 所以我开始问自己是否有一种方法可以在Java中拥有一个固定大小的优先级队列。我应该这样表现: 该物品是否比已存储的物品更好?如果是,请将其插入相应位置,并将评级最小的元件扔掉。
有人有想法吗?再次非常感谢!
马可
I am calculating a large number of possible resulting combinations of an algortihm. To sort this combinations I rate them with a double value und store them in PriorityQueue. Currently, there are about 200k items in that queue which is pretty much memory intesive. Acutally, I only need lets say the best 1000 or 100 of all items in the list.
So I just started to ask myself if there is a way to have a priority queue with a fixed size in Java. I should behave like this:
Is the item better than one of the allready stored? If yes, insert it to the according position and throw the element with the least rating away.
Does anyone have an idea? Thanks very much again!
Marco
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
或者我误解了你的问题?
编辑:忘记提及,要使其工作,您可能必须反转您的 comparTo 函数,因为它会丢弃每个周期中优先级最高的函数。 (如果 a “更好”b 比较 (a, b) 应该返回一个正数。
保持最大数字的示例使用如下所示:
or did I missunderstand your question?
edit: forgot to mention that for this to work you probably have to invert your comparTo function since it will throw away the one with highest priority each cycle. (if a is "better" b compare (a, b) should return a positvie number.
example to keep the biggest numbers use something like this:
MinMaxPriorityQueue
,Google Guava确实有一个用于维护队列的类,当添加超出集合最大大小的项目时,它会比较这些项目以找到要删除的项目,从而创建空间:
MinMaxPriorityQueue
自版本 8 起可在 Google Guava 中找到。EvictingQueue
顺便说一句,如果您只想删除最旧的元素没有对对象的值进行任何比较,Google Guava 15 获得了
EvictingQueue
类。MinMaxPriorityQueue
, Google GuavaThere is indeed a class for maintaining a queue that, when adding an item that would exceed the maximum size of the collection, compares the items to find an item to delete and thereby create room:
MinMaxPriorityQueue
found in Google Guava as of version 8.EvictingQueue
By the way, if you merely want deleting the oldest element without doing any comparison of the objects’ values, Google Guava 15 gained the
EvictingQueue
class.Apache Lucene 中有一个固定大小的优先级队列: http://lucene.apache.org/java/2_4_1/api/org/apache/lucene/util/PriorityQueue.html
根据我的测试,它具有出色的性能。
There is a fixed size priority queue in Apache Lucene: http://lucene.apache.org/java/2_4_1/api/org/apache/lucene/util/PriorityQueue.html
It has excellent performance based on my tests.
使用排序集:
Use SortedSet:
如果队列的最小元素小于当前元素(在您的情况下,评级更差),则只需
poll()
队列。这假设您有某种组合类,它实现了 Comparable,可以比较组合的评级。
编辑:澄清一下,我的示例中的
Iterable
不需要预先填充。例如,下面的Iterable
将为您提供int
可以表示的所有自然数:正如您所见,内存消耗非常适中 - 超过 20 亿值,您需要两个对象(
Iterable
和Iterator
)加上一个int
。当然,您可以很容易地调整我的代码,这样它就不会使用 Iterable - 我只是使用它,因为它是表示序列的一种优雅的方式(而且,我已经做了太多的 Python 和C# ☺)。
Just
poll()
the queue if its least element is less than (in your case, has worse rating than) the current element.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 anIterable<Integer>
that will give you all natural numbers anint
can represent:Memory consumption is very modest, as you can see - for over 2 billion values, you need two objects (the
Iterable
and theIterator
) plus oneint
.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# ☺).更好的方法是更严格地调整队列中的内容,在程序运行时删除和追加队列。听起来在将某些项目添加到队列中之前会有一些空间来排除它们。可以说,这比重新发明轮子更简单。
A better approach would be to more tightly moderate what goes on the queue, removing and appending to it as the program runs. It sounds like there would be some room to exclude some the items before you add them on the queue. It would be simpler than reinventing the wheel so to speak.
我的优先级队列的大多数用例都需要大小限制。目前尚不清楚为什么 Java 设计没有从具有强制大小限制的
ArrayBlockingQueue
扩展PriorityBlockingQueue
。在没有从上面的答案中查看第三方类的情况下,您需要同步限制控制。
Most of my use cases of a priority queue required a size limit. It's not clear why Java design did not extend the
PriorityBlockingQueue
from anArrayBlockingQueue
with mandatory size limit.Without having looked into third party classes from answers above, you need a synchronized limit control.
每次添加项目时只保留前 1000 个项目似乎很自然,但是
PriorityQueue
没有提供任何东西来优雅地实现这一点。也许您可以在方法中执行类似以下操作,而不是使用PriorityQueue
:It seems natural to just keep the top 1000 each time you add an item, but the
PriorityQueue
doesn't offer anything to achieve that gracefully. Maybe you can, instead of using aPriorityQueue
, do something like this in a method: