Top-Themen

Aktuelle Themen (A bis Z)

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit

Sortierung eigener Objekte in einer ArrayList mit Comparable und Comparator

Mitglied: suchong

suchong (Level 1) - Jetzt verbinden

31.10.2011, aktualisiert 23:41 Uhr, 14570 Aufrufe

In Java lassen sich die Wrapper-Klassen wie Byte, Short, Integer, Long, Float, Double und String mühelos mit den Methoden in den Klassen Arrays und Collections sortieren, da diese Wrapper-Klassen alle das Interface Comparable implementieren. Was aber, wenn man eigene Objekte sortiert haben will? Der folgende Beitrag erläutert das anhand der Klasse ArrayList mit der eigenen Klasse Auto.

Zuerst sei das Interface Comparable erläutert. Eine ArrayList ist eine Klasse, welche das Interface List implementiert. Deshalb sollte bei der Instantierung zuerst als Typ das Interface und danach den Konstruktor der Klasse angeben. Will man Objekte des Typs String in eine ArrayList speichern, kann die Liste wie folgt angelegt werden:

01.
List<String> liste = new ArrayList<String>();
Wir haben nun eine Referenz mit dem Bezeichner liste erzeugt, welche auf ein Objekt des Typs Arraylist referenziert. Die liste ist typsicher, d.h. es können nur Objekte des Typs String hinzugefügt werden. Versucht man Objekte eines anderen Typs hinzuzufügen, wird der Code schon gar nicht kompiliert.

Die Klasse ArrayList implementiert die Methode add(), welches das Hinzufügen von Objekten erlaubt, also für die liste:

01.
liste.add("Hallo"); 
02.
liste.add("Welt");
Will man nun liste sortieren, verwendet man in Java die Klasse Collections, welche viele nützliche Methoden enthält, u.a. die Methode sort()

01.
Collections.sort(liste);
Damit ist die liste sortiert. So einfach geht das mit allen Wrapper-Klassen wie Byte, Short, Long, Float, Double und eben String, da diese das Interface Comparable von Haus aus implementieren.

Was aber, wenn man eigene Objekte mit mehreren Feldern sortieren will? Die JVM kann natürlich nicht wissen, nach welchem Feld sortiert werden soll. Deshalb muss die eigene Klasse das Interface Comparable implementieren resp. deren Methode compareTo(), welche angibt, nach was sortiert werden soll. Angenommen es gibt eine Klasse Auto mit den Feldern Marke und Inverkehrsetzung und die Sortierung soll nach der Marke vorgenommen werden, dann kann die Klasse Auto wie folgt aussehen:

01.
public class Auto implements Comparable<Auto>{ 
02.
	private String marke; 
03.
	private int inv; 
04.
	 
05.
	public Auto(String m, int i) { 
06.
		this.marke = m; 
07.
		this.inv = i; 
08.
09.
 
10.
	public String getMarke() { 
11.
		return this.marke; 
12.
13.
	 
14.
	public String toString() { 
15.
		return this.marke + " (" + this.inv + ")"; 
16.
17.
	 
18.
	@Override 
19.
	public int compareTo(Auto auto) { 
20.
		return this.marke.compareTo(auto.getMarke()); 
21.
22.
}
Nun enthält die Liste nicht mehr String Typen, sondern Autos. Musterhaft könnte eine Beispielklasse so aussehen:

01.
import java.util.ArrayList; 
02.
import java.util.Collections; 
03.
import java.util.List; 
04.
 
05.
public class AutoListeBeispiel { 
06.
	public static void main(String[] args) { 
07.
		 
08.
		List<Auto> autos = new ArrayList<Auto>(); 
09.
		 
10.
		autos.add(new Auto("Mercedes", 2007)); 
11.
		autos.add(new Auto("Audi A8", 2010)); 
12.
		 
13.
		Collections.sort(autos); 
14.
		 
15.
		for (Auto a : autos) { 
16.
			System.out.println(a); 
17.
18.
19.
}
Die for-Schleife gibt die Liste wie folgt sortiert aus:

Audi A8 (2010)
Mercedes (2007)

So kann jede eigene Klasse sortiert werden. Implementiert die eigene Klasse das Interface Comparable können die Objekte auch in sortierte Collections wie TreeSet oder TreeMap eingefügt werden.

Was aber, wenn die Klasse nach unterschiedlichen Feldern sortiert werden muss? Hier kommt das Interface Comparator ins Spiel.

Der aufmerksame Leser wird bemerkt haben, dass mit Comparable nur ein Feld der eigenen Klasse sortiert werden kann. Dies, weil die Methodensignatur compareTo(Object anotherObject) lautet und sich der Vergleich mit this d.h. mit dem eigenen Objekt durchgeführt werden muss. Der return Wert von
01.
return this.marke.compareTo(auto.getMarke())
ist nagativ falls this.marke < auto.getMarke()
0 falls this.marke = auto.getMarke()
oder positiv falls this.marke > auto.getMarke()

Statt einer aufsteigenden kann man eine absteigende Sortierung durchführen, wenn man zuerst das auto.getMarke() mit this.marke vergleicht.

Nun zum eigentlichen Thema. Nehmen wir an, wir möchten nach Automarke oder nach Inverkehrsetzung sortieren. Hierzu braucht die Klasse Auto nicht mehr das Interface Comparable zu implementieren. Damit wir ausserhalb der Klasse Auto auf das Feld inv zugreifen können, fügen wir der Klasse Auto zuerst eine Gettermethode getInv() hinzu. Ebenfalls wurde die Methode toString() überschrieben, so dass beim Aufruf die Fahrzeugmarke sowie das Jahr der Inverkehrssetzung in Klammern zurückgeliefert wird.

01.
public class Auto { 
02.
	private String marke; 
03.
	private int inv; 
04.
	 
05.
	public Auto(String m, int i) { 
06.
		this.marke = m; 
07.
		this.inv = i; 
08.
09.
 
10.
	public String getMarke() { 
11.
		return this.marke; 
12.
13.
	 
14.
	public int getInv() { 
15.
		return this.inv; 
16.
17.
	 
18.
	public String toString() { 
19.
		return this.marke + " (" + this.inv + ")"; 
20.
21.
}
Wo wird nun gesagt, wie sortiert werden soll? Hierzu definieren wir eine eigene Klasse, welche das Interface Comparator implementiert. Die erste Klasse soll nach Marke sortieren, also erstellen wir eine neue Klasse SortMarke:

01.
import java.util.Comparator; 
02.
 
03.
public class SortMarke implements Comparator<Auto>{ 
04.
 
05.
	@Override 
06.
	public int compare(Auto a1, Auto a2) { 
07.
		return a1.getMarke().compareTo(a2.getMarke()); 
08.
09.
}
Im Code sieht man den Unterschied zwischen den Methodensignaturen vom compareTo und compare. Compare hat zwei Argumente des Typs Objekt. Der Vergleich erfolgt nicht mehr zwischen this und einem anderen Objekt, sondern im obigen Fall zwischen a1 und a2. Für die Sortierung nach dem Jahr der Inverkehrssetzung kann man folgende Klasse verwenden:

01.
import java.util.Comparator; 
02.
 
03.
public class SortInv implements Comparator<Auto>{ 
04.
 
05.
	@Override 
06.
	public int compare(Auto a1, Auto a2) { 
07.
		return a1.getInv() - a2.getInv(); 
08.
09.
}
Nach dem Return wird hier nicht mehr mit compareTo verglichen, sondern die Zahl von a2 von a1 substrahiert. Dies ergibt dasselbe Ergebnis wie oben gezeigt: falls a1.getInv() < f2.getInv() dann gebe ein negativer Wert zurück etc.

Die Sortierung nach beliebigen Feldern hat Programmieraufwand verursacht, dafür ist der Aufruf ziemlich einfach. Das folgende Programm implementiert die Methode main(), erzeugt zwei Fahrzeuge, sortiert nach Marke und gibt die Ergebnisse aus, sortiert nach Jahr der Inverkehrssetzung und gibt die Ergebnisse aus:

01.
import java.util.ArrayList; 
02.
import java.util.Collections; 
03.
import java.util.List; 
04.
 
05.
public class AutoListeBeispiel { 
06.
	public static void main(String[] args) { 
07.
		 
08.
		List<Auto> autos = new ArrayList<Auto>(); 
09.
		 
10.
		autos.add(new Auto("Mercedes", 2007)); 
11.
		autos.add(new Auto("Audi A8", 2010)); 
12.
		 
13.
		Collections.sort(autos, new SortMarke()); 
14.
		 
15.
		System.out.println("Sortierung nach Fahrzeugmarke:"); 
16.
		for (Auto a : autos) { 
17.
			System.out.println(a); 
18.
19.
		 
20.
		Collections.sort(autos, new SortInv()); 
21.
		 
22.
		System.out.println("\nSortierung nach Jahr der Inverkehrssetzung:"); 
23.
		for (Auto a : autos) { 
24.
			System.out.println(a); 
25.
26.
27.
}
Da nun die Klasse Auto nicht mehr sich selbst sortiert, muss man beim Aufruf von Collections.sort() ein Objekt des Typs Comparator mitgeben. Dies wird im ersten Aufruf mit new SortMarke() und beim zweiten Aufruf mit SortInv() gewährleistet. Und der Output sieht wie folgt aus:

Sortierung nach Fahrzeugmarke:
Audi A8 (2010)
Mercedes (2007)

Sortierung nach Jahr der Inverkehrssetzung:
Mercedes (2007)
Audi A8 (2010)

Der Quellcode kann mit wenig Aufwand aus diesem Beitrag kopiert und kompiliert werden. Falls der Quellcode und die kompilierten Klassen gewünscht werden, bitte Nachricht an mich. Beim Vorliegen der kompilierten Klassen kann das Beispiel mit

java AutoListeBeispiel

gestartet werden. Bitte auf Gross- bzw. Kleinschreibung achten, da Java in Groß-/Kleinschreibung unterscheidet!
Ähnliche Inhalte
DSL, VDSL

Bei Unitymedia eine eigene IPv4 mit DS bekommen

Tipp von matze2090DSL, VDSL1 Kommentar

Hallo, ich hatte noch vor kurzem eine DS-Lite Verbindung bei Unitymedia. Das nachteil zu DS ist das Port Forwarding ...

Windows 10

Microsoft Edge: Erster Benchmark und eigene Eindrücke

Erfahrungsbericht von FrankWindows 101 Kommentar

Nach dem Microsoft heute den Build 10240 für das Insider Preview Programm veröffentlicht hat, wurde auch die finale Version ...

Internet

Landgericht Hamburg distanziert sich von eigener Rechtsprechung zur Linkhaftung

Information von sabinesInternet2 Kommentare

Rolle rückwärts, teilweise: "Das Landgericht (LG) Hamburg hält nicht länger an einem strengen Haftungsmaßstab bei Verlinkungen auf urheberrechtsverletzende Inhalte ...

E-Mail

Wenn die eigene Domain für Spamversand missbraucht wird und was man dagegen tun kann

Anleitung von LordGurkeE-Mail10 Kommentare

Wieso steht da unsere Domain im Absender? Das kann doch nicht sein! Die Absenderadresse einer E-Mail kann man genau ...

Neue Wissensbeiträge
Sonstige Systeme
Es war einmal ein BeOS - Wer erinnert sich noch?
Information von BassFishFox vor 1 TagSonstige Systeme5 Kommentare

Hallo, Bin gerade ueber Haiku gestolpert, von dessen Existenz als "Nachfolger des BeOS" ich wusste nur mich nie wirklich ...

Datenschutz

Microsoft und DSGVO - ob das wohl jemals klappt (Probleme beim Datenabfluss für Office Pro Plus)?

Tipp von VGem-e vor 1 TagDatenschutz3 Kommentare

Servus Kollegen, siehe Aber wer setzt schon MS Office Pro Plus ein? Wie dann der Stand beim "normalen" MS ...

Windows 10

Macht Windows 10.1809 Probleme mit gemappten Netzlaufwerken (betrifft wohl insbes. AMD-Hardware und Trend Micro AV-Produkte)?

Tipp von VGem-e vor 1 TagWindows 103 Kommentare

Moin Kollegen, grad dazu gefunden und Hatten wir dies nicht bei früheren W10-Upgrades ebenfalls? Da bleibt nur, das Upgrade ...

Humor (lol)

Das neue Miniatur Wunderland OFFICIAL VIDEO - worlds largest model railway - railroad

Information von StefanKittel vor 2 TagenHumor (lol)2 Kommentare

Hallo, wer noch nie im Miniatur Wunderland war, sollte es dringend mal nachholen. Es gibt eine neues Video. Viele ...

Heiß diskutierte Inhalte
LAN, WAN, Wireless
Gäste-WLAN durch DD-WRT AP nach einem MikroTik Routerboard
Frage von NukolarLAN, WAN, Wireless16 Kommentare

Hallo, wie der Titel schon sagt möchte ich gerne ein Gäste-WLAN innerhalb eines bestehenden LANs einrichten. Dass die Gäste ...

DSL, VDSL
DSL Monitoring Tool - Quick and dirty?
Frage von george44DSL, VDSL15 Kommentare

Liebe Gemeinde, ich suche ein einfaches und vor allem schnell zu installierendes Monitoring-Tool zur kontinuierlichen Dokumentation (nur) der Internetanbindung. ...

Exchange Server
Outlook findet Postfach nicht
Frage von MaximaxExchange Server11 Kommentare

Hallo, und zwar haben wir auf der Arbeit ein kleines (großes) Exchange 2016 Problem. Exchange meldete gestern, dass die ...

Informationsdienste
Probleme auf dem Server
Frage von LangeLangeInformationsdienste9 Kommentare

Hallo zusammen, ich betreibe die Seite Keine Werbelinks. In der Analyse stellen wir fest, dass die Ladezeit in der ...