PriorityQueue mit Einfügereihenfolge

patrick81

Mitglied
Hallo zusammen

Ich implementiere gerade eine Jobqueue. Da die Jobs unterschiedlich hohe Prioritäten besitzen, verwende ich eine Priorityqueue. Das Problem ist, wenn zwei Jobs dieselbe Priorität besitzen soll die Einfügereihenfolge beachtet werden. Die Standart Priorityqueue von Java SE berücksichtig dies nicht und wählt dann eher zufällig ein Job aus.
Gibt es eine PriorityQueue die bei comparTo == 0 die Einfügereihenfolge der Elemente beachtet.

Besten Dank im Voraus
 

truesoul

Top Contributor
Hallo.

Also ich würde es an deiner Stelle selber erstellen. Ich hatte es mal so gemacht:

Die Klasse Aufgabe die Comparable implementiert:
Java:
class Aufgaben implements Comparable<Aufgaben> {
	String beschreibung;
	Date termin;
	Prioritaet prioritaet;

	public Aufgaben(String beschreibung, Date termin, Prioritaet prioritaet) {
		this.beschreibung = beschreibung;
		this.termin = termin;
		this.prioritaet = prioritaet;
	}

	public Aufgaben(String beschreibung, String termin, Prioritaet prioritaet)
			throws ParseException {
		this.beschreibung = beschreibung;
		this.prioritaet = prioritaet;

		// "06.07.11"
		DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
		this.termin = df.parse(termin);

		Calendar cal = Calendar.getInstance();
		cal.setTime(this.termin);

		int jahr = cal.get( Calendar.YEAR );

		if( jahr<2010 || jahr>3000 )
			throw new IllegalArgumentException("Bitte das Jahr " +
					"im Bereich [2011...3000] benutzen!");

	}

	public String toString() {
		String s = "";

		DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM);
		String t = df.format(termin);

		s += "Aufgabe: " + beschreibung + "\n";
		s += "Zu erledigen am " + t + "\n";
		s += "Priorität: " + prioritaet;

		return s;
	}

	public int compareTo(Aufgaben a2) {
		if(termin.getTime() != a2.termin.getTime())
			return (int)(termin.getTime() - a2.termin.getTime());

		return a2.prioritaet.ordinal() - prioritaet.ordinal();
	}
}

BeispielQueue mit der Main:
Java:
public class BeispielQueue {

	public static void main(String[] args) throws Exception {


		Aufgaben a1 = new Aufgaben("Autowaesche",
				"16.07.11", Prioritaet.NIEDRIG);
		Aufgaben a2 = new Aufgaben("EMails abrufen",
				"15.07.11", Prioritaet.NIEDRIG);
		Aufgaben a3 = new Aufgaben("Tom anrufen",
				"15.07.11", Prioritaet.DRINGEND);
		Aufgaben a4 = new Aufgaben("Einkaufen",
				"15.07.11", Prioritaet.MITTEL);

		Queue<Aufgaben> q1 = new PriorityQueue<Aufgaben>();

		q1.offer(a2);
		q1.offer(a3);
		q1.offer(a1);
		q1.offer(a4);

		//Aufgaben erledigen!
		while( !q1.isEmpty() ) {
			System.out.println("----------------------------");
			System.out.println( q1.poll() );
		}
	}
}

Prioritaet
Java:
enum Prioritaet {
	NIEDRIG("niedrig"),
	MITTEL("mittel"),
	HOCH("hoch"),
	DRINGEND("dringend"); 

	String name;

	Prioritaet(String name) {
		this.name = name;
	}

	public String toString() { return name; }
}

Vielleicht hilft dir das weiter ;) Naja für das Datum kannst du z.B die Zeit angeben die das Objekt der Queue geaddet worden ist. Wie du es machst musste dann mal schauen :)

Mfg
 

nrg

Top Contributor
also ich verstehe dein problem nicht. die sortierung der queue ist doch abhängig von deiner klasse, von der du objekte in der queue hälst. dort implementierst du ganz einfach Comparable und überschreibst die compareTo nach Wunsch
 

Ariol

Top Contributor
Java:
 class FIFOEntry<E extends Comparable<? super E>>
     implements Comparable<FIFOEntry<E>> {
   final static AtomicLong seq = new AtomicLong();
   final long seqNum;
   final E entry;
   public FIFOEntry(E entry) {
     seqNum = seq.getAndIncrement();
     this.entry = entry;
   }
   public E getEntry() { return entry; }
   public int compareTo(FIFOEntry<E> other) {
     int res = entry.compareTo(other.entry);
     if (res == 0 && other.entry != this.entry)
       res = (seqNum < other.seqNum ? -1 : 1);
     return res;
   }
 }

und dann deine Jobs mit
Java:
queue.add(new FIFOEntry(job));

Wenn 2 Jobs bei compareTo 0 zurückgeben wird der Zähler "seqNum" verwendet.

Quelle
 

patrick81

Mitglied
Danke für eure Antworten.

Die Lösung mit dem FIFOEntry ist genau das was ich gesucht habe. Die Klasse die compareTo implementiert kann ich leider nicht nach Wunsch ändern.
 

nrg

Top Contributor
häää? die würdest du doch jetzt in dem fall mit FIFOEntry ersetzen... ja egal. solange dir geholfen ist
 

patrick81

Mitglied
@nrg
Nein, vorher habe ich den Job einfach der Queue hinzugefühgt.

Java:
queue.add(job);

nun wrappe ich dieses Objekt in ein FIFOEntry

Java:
queue.add(new FIFOEntry(job));

deine Lösung wäre natürlich einfacher. Ich poste morgen mal mein code, vieleicht habe ich auch noch etwas übersehen.

gr.
 

Ähnliche Java Themen


Oben