fj.data.PriorityQueue Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
package fj.data;
import fj.Equal;
import fj.F;
import fj.F2;
import fj.Monoid;
import fj.Ord;
import fj.P;
import fj.P2;
import fj.Show;
import fj.data.fingertrees.FingerTree;
import static fj.Function.compose;
import static fj.data.Option.none;
import static fj.data.Option.some;
/**
* A priority queue implementation backed by a
* {@link fj.data.fingertrees.FingerTree}. The finger tree nodes are
* annotated with type K, are combined using a monoid of K and both the
* key and value are stored in the leaf. Priorities of the same value
* are returned FIFO (first in, first out).
*
* Created by MarkPerry on 31 May 16.
*/
public final class PriorityQueue {
private final FingerTree> ftree;
private final Equal equal;
private PriorityQueue(Equal e, FingerTree> ft) {
equal = e;
ftree = ft;
}
/**
* Creates a priority queue from a finger tree.
*/
public static PriorityQueue priorityQueue(Equal e, FingerTree> ft) {
return new PriorityQueue<>(e, ft);
}
/**
* Creates an empty priority queue.
*
* @param m A monoid to combine node annotations.
* @param e A value to compare key equality.
*/
public static PriorityQueue empty(Monoid m, Equal e) {
return priorityQueue(e, FingerTree.empty(m, P2.__1()));
}
/**
* An empty priority queue with integer priorities.
*/
public static PriorityQueue emptyInt() {
return empty(Monoid.intMaxMonoid, Equal.intEqual);
}
/**
* Maps the values in each node with function f.
*/
public PriorityQueue map(F f) {
return priorityQueue(equal,
ftree.map(P2.map2_(f),
FingerTree.measured(ftree.measured().monoid(), P2.__1())
)
);
}
/**
* Filters nodes based on the value inside each node.
*/
public PriorityQueue filterValues(F f) {
return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._2())));
}
/**
* Filters the nodes based on the annotation of each node.
*/
public PriorityQueue filterKeys(F f) {
return priorityQueue(equal, ftree.filter(p2 -> f.f(p2._1())));
}
/**
* Is the tree empty?
*/
public boolean isEmpty() {
return ftree.isEmpty();
}
/**
* If the tree is not empty, returns the node with highest priority otherwise returns nothing.
*/
public Option> top() {
return unqueue(none(), (top, tail) -> some(top));
}
/**
* Returns all the elements of the queue with the highest (same) priority.
*/
public List> topN() {
return toStream().uncons(
List.nil(),
top -> tail -> List.cons(top, tail._1().takeWhile(compose(equal.eq(top._1()), P2.__1())).toList())
);
}
/**
* Adds a node with priority k and value a. This operation take O(1).
*/
public PriorityQueue enqueue(K k, A a) {
return priorityQueue(equal, ftree.snoc(P.p(k, a)));
}
/**
* Adds nodes using the list of products with priority k and value a. This operation takes O(list.length()).
*/
public PriorityQueue enqueue(List> list) {
return list.foldLeft((pq, p) -> pq.enqueue(p._1(), p._2()), this);
}
/**
* Does the priority k exist already?
*/
public boolean contains(final K k) {
return !ftree.split(equal.eq(k))._2().isEmpty();
}
/**
* Adds nodes using the iterable of products with priority k and value a.
*/
public PriorityQueue enqueue(Iterable> it) {
PriorityQueue result = this;
for (P2 p: it) {
result = result.enqueue(p);
}
return result;
}
/**
* Adds a node with priority k and value a. This operation take O(1).
*/
public PriorityQueue enqueue(P2 p) {
return enqueue(p._1(), p._2());
}
/**
* Removes the node with the highest priority.
*/
public PriorityQueue dequeue() {
return unqueue(this, (top, tail) -> tail);
}
/**
* Returns a tuple of the node with the highest priority and the rest of the priority queue.
*/
public P2