Advanced Java Services | LinkedList und PriorityQueue |
Es gibt drei nicht blockierende Queues, Linkedlist, PriorityQueue und ConcurrentLinkedQueue.
Bounded | FIFO | LIFO | Head = Longest time element | Head = Least element | Insert at tail | Retrieve from head | Permits null | Thread safe | |
LinkedList | x | x | x | x | |||||
PriorityQueue | x | ||||||||
ConcurrentLinkedQueue | x | x | x | x | x |
Die Klasse LinkedList fällt aus der Reihe, weil sie bereits in 1.2 eingeführt worden ist und nachträglich so erweitert wurde, daß sie das Interface Queue (1.5) und das Interface Deque (1.6) implementiert. Aus diesem Grund leitet sich LinkedList auch nicht von AbstractQueue ab, sondern direkt von AbstractSequentialList (1.2). Linkedlist ist die einzige Queue, die das Interface List implementiert hat.
An unbounded priority queue based on a priority heap. The elements of the priority queue are ordered according to their
natural ordering, or by a Comparator provided at queue construction time, depending on which constructor is used.
A priority queue does not permit null elements. A priority queue relying on natural ordering also does not permit
insertion of non-comparable objects (doing so may result in ClassCastException).
The head of this queue is the least element with respect to the specified ordering. If multiple elements are tied for
least value, the head is one of those elements -- ties are broken arbitrarily. The queue retrieval operations poll,
remove, peek, and element access the element at the head of the queue.
A priority queue is unbounded, but has an internal capacity governing the size of an array used to store the elements
on the queue. It is always at least as large as the queue size. As elements are added to a priority queue, its capacity
grows automatically. The details of the growth policy are not specified.
This class and its iterator implement all of the optional methods of the Collection and Iterator interfaces. The Iterator
provided in method iterator() is not guaranteed to traverse the elements of the priority queue in any particular order.
If you need ordered traversal, consider using Arrays.sort(pq.toArray()).
Note that this implementation is not synchronized. Multiple threads should not access a PriorityQueue instance concurrently
if any of the threads modifies the queue. Instead, use the thread-safe PriorityBlockingQueue class.
Implementation note: this implementation provides O(log(n)) time for the enqueing and dequeing methods
(offer, poll, remove() and add); linear time for the remove(Object) and contains(Object) methods; and constant time for
the retrieval methods (peek, element, and size).
Es können nur Elemente aufgenommen werden, deren Klasse das Interface Comparable implementiert hat oder zu der es eine Vergleichsklasse (Comparator) gibt. Eine PriorityQueue verwendet beim Aufnehmen von Elementen die Methode compareTo() oder im zweiten Fall die Methode compare() um das alphabetische kleinste Element an die Spitze (Head) zu bringen. Egal welche Methode zum Entnehmen eines Elements verwendet wird, es kann immer nur das Headelement entnommen werden. Jede Entnahme löst einen Vergleich aus, da dann das Headelement aktualisiert werden muß. Die PriorityQueue ist keine blockierende Queue, die Methoden put() und take() existieren hier (noch) nicht. Ist die Queue leer, so werfen die Methoden entweder eine Exception oder sie liefern null.
Das einfache Beispiel zeigt die Aufrufe der Vergleichsfunktion bei der Aufnahme und Entnahme von Elementen.
Es wird eine Klasse MyString angelegt, die das Interface Comparable implementiert und eine Meldung ausgibt falls die Methode compareTo() gerufen wird.
Auf diese Weise wird der Algorithmus sichtbar mit dem die PriorityQueue arbeitet. Die Queue ist also keineswegs vollständig geordnet, nur das Headelemnent wird an die erste Stelle gesetzt.
class MyString implements Comparable<MyString> { String string; public MyString(String string) { this.string = string; } @Override public int compareTo(MyString ob) { System.out.println("compareTo: " + this.string + " " + ob.string); return this.string.compareTo(ob.toString()); } @Override public String toString() { return string; } }
Main nimmt vier Elemente auf und entfernt diese nacheinander. Jedesmal werden die verbleibenden Elemente aufgelistet und man sieht die Aufrufe von compareTo().
public class PriorityQueueDemo_01 { public static void main(String[] args) { PriorityQueue<MyString> pq = new PriorityQueue<>(); System.out.println("Aufzunehmendes Element: eins" ); pq.add(new MyString("eins")); System.out.println("Enthaltene Elemente: " + pq); System.out.println("Aufzunehmendes Element: zwei" ); pq.add(new MyString("zwei")); System.out.println("Enthaltene Elemente: " + pq); System.out.println("Aufzunehmendes Element: drei" ); pq.add(new MyString("drei")); System.out.println("Enthaltene Elemente: " + pq); System.out.println("Aufzunehmendes Element: vier" ); pq.add(new MyString("vier")); System.out.println("Enthaltene Elemente: " + pq); System.out.println("--------------------------------"); System.out.println("head = " + pq.element()); System.out.println("poll = " + pq.poll()); // holt das Headelement raus // bestimmt den neuen Head, bevor der alte Head geliefert wird System.out.println("head = " + pq.element()); System.out.println("Enthaltene Elemente: " + pq); System.out.println("--------------------------------"); System.out.println("head = " + pq.element()); System.out.println("poll = " + pq.poll()); System.out.println("head = " + pq.element()); System.out.println("Enthaltene Elemente: " + pq); System.out.println("--------------------------------"); System.out.println("head = " + pq.element()); System.out.println("poll = " + pq.poll()); System.out.println("head = " + pq.element()); System.out.println("Enthaltene Elemente:" + pq); System.out.println("--------------------------------"); System.out.println("head = " + pq.element()); System.out.println("poll = " + pq.poll()); //System.out.println("head = " + pq.element()); // NoSuchElementException System.out.println("Enthaltene Elemente: " + pq); } }
Konsolausgabe
Aufzunehmendes Element: eins Enthaltene Elemente: [eins] Aufzunehmendes Element: zwei compareTo: zwei eins Enthaltene Elemente: [eins, zwei] Aufzunehmendes Element: drei compareTo: drei eins Enthaltene Elemente: [drei, zwei, eins] Aufzunehmendes Element: vier compareTo: vier zwei compareTo: vier drei Enthaltene Elemente: [drei, vier, eins, zwei] -------------------------------- head = drei compareTo: vier eins compareTo: zwei eins poll = drei head = eins Enthaltene Elemente: [eins, vier, zwei] -------------------------------- head = eins compareTo: zwei vier poll = eins head = vier Enthaltene Elemente: [vier, zwei] -------------------------------- head = vier poll = vier head = zwei Enthaltene Elemente:[zwei] -------------------------------- head = zwei poll = zwei Enthaltene Elemente: []