I\'m trying to implement a stable (first in first out) priority queue in Java. Supposing that the key is a name and the value is an age, I know I can make an unstable prior
You need something like this:
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());
}
}
}
Very simple implementation based on multiple lists and TreeMap
I've done today to solve some task:
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));
}
}
No comparator used for elements, but used internally by TreeMap
for queues. My case is that I have only a few of priorities, but a lot of elements, so it should go faster than something using element comparison.
Keap-based PriorityQueue is naturally stable. It's written in Kotlin, so it can replace java.util.PriorityQueue
in Java code.