[英]Making a Java PriorityQueue into a stable priority queue
我正在尝试在 Java 中实现一个稳定的(先进先出)优先级队列。 假设键是一个名字,值是一个年龄,我知道我可以像这样制作一个不稳定的优先级队列:
Queue<Map.Entry<String, Integer>> pq = new PriorityQueue<Map.Entry<String, Integer>>(100, ageComparator);
这几乎完成了我需要它做的所有事情,除了它在我插入(或删除它们)时不保持键值对的顺序。
我通过制作 LinkedList 找到了一种“解决方法”,它提供了基本上所有相同的功能,只是它不包含带有比较器选项的构造函数,而且我觉得它必须更慢,因为我保持了值排序通过在每个队列操作之后调用Collections.sort()
。
所以我想确实有两个我感兴趣的选项。首先,我如何编辑上面的 PriorityQueue 以保持插入和删除顺序? 或者第二,如何强制我的 LinkedList 选项立即使用比较器,而不必对每个操作调用排序? 谢谢!
编辑:
感谢您在发布的第一条评论中提出的好问题。 通过FIFO,我的意思是对于具有相等值的键值对,应该首先提取最先放入的键值对。
你需要这样的东西:
import java.util.AbstractMap;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.concurrent.atomic.AtomicInteger;
public class PriorityTest {
@SuppressWarnings("serial")
private static class Entry extends AbstractMap.SimpleEntry<String, Integer> {
private final static AtomicInteger seq = new AtomicInteger(0);
final int order;
public Entry(final String _key, final Integer _value) {
super(_key, _value);
order = seq.incrementAndGet();
}
}
private static class OrderedComparator implements Comparator<Entry> {
@Override
public int compare(final Entry _e1, final Entry _e2) {
int r = _e1.getValue().compareTo(_e2.getValue());
if (r == 0)
return Integer.compare(_e1.order, _e2.order);
return r;
}
}
public static void main(String[] args) {
final PriorityQueue<Entry> pq = new PriorityQueue<Entry>(10, new OrderedComparator());
pq.add(new Entry("Jane", 22));
pq.add(new Entry("John", 15));
pq.add(new Entry("Bill", 45));
pq.add(new Entry("Bob", 22));
while(!pq.isEmpty()) {
System.out.println(pq.remove());
}
}
}
基于 Keap 的 PriorityQueue自然是稳定的。 它是用 Kotlin 编写的,因此它可以替换 Java 代码java.util.PriorityQueue
。
基于多个列表和TreeMap
我今天完成的非常简单的实现来解决一些任务:
import javax.annotation.Nonnull;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.Function;
public class PriorityFifo<E> {
protected TreeMap<Integer, LinkedList<E>> storage = new TreeMap<>();
public void push(E element, int priority) {
storage.computeIfAbsent(priority, it -> new LinkedList<>()).addLast(element);
}
public Optional<E> poll() {
return doWithNextElement(LinkedList::pollFirst);
}
public Optional<E> peek() {
return doWithNextElement(LinkedList::getFirst);
}
protected Optional<E> doWithNextElement(@Nonnull Function<LinkedList<E>, E> f) {
Entry<Integer, LinkedList<E>> entry = storage.firstEntry();
if (entry==null)
return Optional.empty();
LinkedList<E> list = entry.getValue();
E element = f.apply(list);
if (list.isEmpty())
storage.remove(entry.getKey());
return Optional.of(Objects.requireNonNull(element));
}
}
没有用于元素的比较器,而是由TreeMap
内部用于队列。 我的情况是我只有几个优先级,但有很多元素,所以它应该比使用元素比较的东西更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.