Zum Inhalt springen

Collection sortieren mit unterschiedlichen Reihenfolgen


Empfohlene Beiträge

Geschrieben

Hallo zusammen,

 

ich stehe etwas auf dem Schlauch und sämtliche Beispiele, die ich gefunden habe, brachten mich nicht wirklich weiter, da sie mein Ausgangsproblem nicht behandelten.

 

Folgendes:
Ich habe ein eigenes Objekt erstellt, welches ich nun sortieren möchte.

Im Grunde beinhaltet das Objekt 2 Attribute, welche im Kern Integerwerte beinhalten (in Wirklichkeit sind da weitere BOs drin, will es aber hier einfach halten).

Also Attribut 1 = Typ Integer

Attribut 2 = Typ Integer

 

Ich habe eine compateTo() Methode geschrieben, sowie hashCode() und equals() implementiert.

Was ich irgendwie nicht abgebildet bekomme ist folgendes:

Ich möchte Attribut 2 absteigend sortieren und innerhalb der absteigenden Sortierung die Werte von Attribut 1 aufsteigend sortieren.

Ich bekomme aber immer nur eine Richtung sortiert, nie beide.

 

Beispiel:
Ich habe eine Liste mit folgenden Wertepaaren

 

  • 100 / 7
  • 110 / 7
  • 120 / 3
  • 130 / 8
  • 099 / 8
  • 080 / 2

Ich bräuchte jetzt folgende Sortierung:

  • 099 / 8
  • 130 / 8
  • 100 / 7
  • 110 / 7
  • 120 / 3
  • 080 / 2

Bekomme ich das mit nem compareTo() oder einem Comperator überhaupt hin?

Hat wer ein Beispiel / Tutorial für mich, was mir hier weiterhelfen könnte? Ich finde immer nur entweder simple Listen mit einem Wert oder es wird alles in eine Richtung sortiert.

 

Gruß

Ganymed

 

Geschrieben

Moin,

vielleicht hilft Dir das (Ist leider C++): 

std::vector<std::pair<int, int>> v;
v.push_back({ 100 , 7 });
v.push_back({ 110 , 7 });
v.push_back({ 120 , 3 });
v.push_back({ 130 , 8 });
v.push_back({ 99 , 8 });
v.push_back({ 80 , 2 });

std::sort(v.begin(), v.end(), [](auto l, auto r) {
	return l.first < r.first;
});

std::sort(v.begin(), v.end(), [](auto l, auto r) {
	return l.second > r.second;
});

So etwas ähnliches sollte doch in Java auch gehen, oder?

Geschrieben

Auseinandernehmen und dann neu zusammenstecken wollte ich halt nicht, sondern über die Java-Methoden machen, das fände ich eleganter.

Ist halt die Frage, wie mächtig die sind oder ob das wirklich nur auf das beschränkt ist, was man so findet.

Vielleicht muss man das ja nur erweitern / anders aufrufen und schon gehts.

:)

 

Geschrieben

Das CompareTo müsste ca. so aussehen:

public int CompareTo(BO other)
{
	if (Value2 == other.Value2)
	{
		return Value1.CompareTo(other.Value1);
	}
	else
	{
		return Value2.CompareTo(other.Value2) * -1;
	}
}

Hab's jetzt nicht getestet, aber das Prinzip sollte stimmen.

Geschrieben (bearbeitet)
vor 2 Stunden schrieb Ganymed:

Bekomme ich das mit nem compareTo() oder einem Comperator überhaupt hin?

Jein.

Wichtig zu verstehen ist, dass sowohl compareTo() als auch ein Comperator dafür gedacht sind, lediglich zwei Objekte zu vergleichen. Du bildest hier mit also die Sortierungsbedingung ab die komplexer ist als bspw. nur < oder >. Man spricht auch davon, dass man nicht nach einer natürlichen Bedingung vergleicht. Das heißt in deinem Vergleich bildest du nur die Wertigkeit deiner Objekte ab => Es wird nur nach Attribut 1 verglichen, wenn Attribut 2 gleich ist.

Die eigentliche Sortierung muss allerdings eine Sortierungsfunktion vornehmen. Deswegen kannst du  Sortierungsklassen (siehe Collections.sort) neben einer Liste deiner Objekte auch einen Comperator übergeben, der dafür sorgt, dass die übergeben Objektliste Anhand deiner definierten Bedingungen im Comperator verglichen werden. Siehe hier zu auch: http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html


Einfach deine Liste sequenziell abarbeiten mit CompareTo() oder einem Comperator führt nicht zu einer vollständigen Sortierung, weil du immer nur die nebeneinander stehenden Wertepaare miteinander verglichen hast.

 

Bearbeitet von Uhu
Geschrieben
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Sortierung
{
	private static class MeinObjekt
	{
		private final int wert1;
		private final int wert2;

		public MeinObjekt(final int wert1, final int wert2)
		{
			this.wert1 = wert1;
			this.wert2 = wert2;
		}

		private int getWert1()
		{
			return wert1;
		}

		private int getWert2()
		{
			return wert2;
		}

		@Override
		public String toString()
		{
			return String.format("%s / %s", getWert1(), getWert2());
		}
	}

	public static void main(final String[] args)
	{
		final List<MeinObjekt> objekte = new ArrayList<>();
		objekte.add(new MeinObjekt(100, 7));
		objekte.add(new MeinObjekt(110, 7));
		objekte.add(new MeinObjekt(120, 3));
		objekte.add(new MeinObjekt(130, 8));
		objekte.add(new MeinObjekt(99, 8));
		objekte.add(new MeinObjekt(80, 2));

		System.out.println("Vorher -----------------------------");
		objekte.forEach(System.out::println);

		System.out.println("Nachher ----------------------------");
		final Comparator<MeinObjekt> nachWert2Absteigend =
				(mo1, mo2) -> Integer.compare(mo2.getWert2(), mo1.getWert2());
		final Comparator<MeinObjekt> nachWert1Aufsteigend =
				(mo1, mo2) -> Integer.compare(mo1.getWert1(), mo2.getWert1());
		objekte.stream()
				.sorted(
						nachWert2Absteigend.thenComparing(nachWert1Aufsteigend))
				.forEach(System.out::println);
	}
}

Ausgabe:

Vorher -----------------------------
100 / 7
110 / 7
120 / 3
130 / 8
99 / 8
80 / 2
Nachher ----------------------------
99 / 8
130 / 8
100 / 7
110 / 7
120 / 3
80 / 2

 

Geschrieben (bearbeitet)

@Uhu

Ich lese mir das mal durch.

@stefan.macke

Lambda Expression kann ich leider nicht verwenden. Ich arbeite mit 1.6.

Habe ich auch noch nicht verwendet, so dass ich das ehrlich gesagt nicht lesen und verstehen kann.

Habe viel davon gehört, würde auch gerne mal eine verständliche Einführung dazu lesen (gerne Deutsch!)

Bearbeitet von Ganymed
Geschrieben
vor 16 Stunden schrieb arlegermi:

Das CompareTo müsste ca. so aussehen:


public int CompareTo(BO other)
{
	if (Value2 == other.Value2)
	{
		return Value1.CompareTo(other.Value1);
	}
	else
	{
		return Value2.CompareTo(other.Value2) * -1;
	}
}

Hab's jetzt nicht getestet, aber das Prinzip sollte stimmen.

Hey, super, das hat funktioniert! :)

Nur "CompareTo" sollte überall "comapreTo" heißen, falls jemand das auch mal nutzen möchte.

 

Vielen Dank an alle!

Geschrieben
vor 6 Minuten schrieb Ganymed:

@Uhu

Ich lese mir das mal durch, das könnte hilfreich sein!

@stefan.macke

Lambda Expression kann ich leider nicht verwenden. Ich arbeite mit 1.6.

Habe ich auch noch nicht verwendet, so dass ich das ehrlich gesagt nicht lesen und verstehen kann.

Habe viel davon gehört, würde auch gerne mal eine verständliche Einführung dazu lesen (gerne Deutsch!)

 

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...