Duplikate aus Liste entfernen

jfkoernjf

Mitglied
Hallo,
ich hatte jetzt schon öfters das Problem, dass ich eine Liste von Objekten habe, die ich von Duplikaten befreien wollte. Das ganze soll natürlich möglichst schick, schnell und elegant gehen.

Stellt euch vor ich habe eine Liste von Personen, die alle einen Vor- und Nachnamen haben.
Jetzt möchte ich jede Person nur einmal in meiner Liste haben.

Bis hier ist es für mich noch ganz klar- einfach ein Set nehmen, equals und hashCode in der Klasse überschreiben und dann mit addAll() hinzufügen.

So jetzt kommts:
Stellt euch vor ich möchte jetzt für jede Familie nur eine Person haben (den Sinn klammern wir jetzt mal aus). Was ist der schönste Weg eine List<Person> jetzt von den lästigen anderen Familienmitgliedern zu befreien?
Am liebsten wäre mir hier sowas wie ein Comparator, den ich für diese eine Operation anwenden kann- aber das gibts sicher nicht oder?

Mir fällt jetzt nur der umständliche Weg hier ein:
- Set<String> für alle Familiennamen erzeugen
- jedes Element in der Liste durchgehen und prüfen, ob der Name im Set vorhanden ist wenn nein hinzufügen und Element in meine Zielliste kopieren

Ich hatte noch die andere Idee von Person eine Klasse abzuleiten und der dann einen eigenen equals() und hashCode zu spendieren- aber irgendwie bin ich mir hier auch unsicher, ob das so schick ist. Um Schreibarbeit zu sparen könnte man hier ja eine anonyme Klasse verwenden.

Also mir gehts nur um schönen Programmierstil.
Wie würdet ihrs machen?
 

Xeonkryptos

Bekanntes Mitglied
Könntest du nicht einfach eine eigene add-Methode schreibe, die vor dem Hinzufügen prüft, ob dieser Name schon vorhanden ist und ihn erst bei nicht auffinden übergibt? Das wäre wohl die einfachste Variante.
 

jfkoernjf

Mitglied
Helf mir mal- wie würdest du das genau machen?
Ich müsste ja in der Add-Methode die ganze Liste durchgehen und in jedes einzelne Objekt hineinschauen und nen String-Vergleich machen.
Ist das bei großen Listen nicht sehr langsam? Oder verstehe ich Dich falsch?
 
N

nillehammer

Gast
Ich müsste ja in der Add-Methode die ganze Liste durchgehen und in jedes einzelne Objekt hineinschauen und nen String-Vergleich machen.
Ist das bei großen Listen nicht sehr langsam? Oder verstehe ich Dich falsch?
Genau das ist der Weg. Wenn Du Dir den Quellcode von z.B. contains() in ArrayList anschaust, machen die auch nix anderes als die komplette Liste durchzuiterieren. Listen sind eben für den Zugriff über Index gemacht. Optimierte Zugriffe bspw. mittels Hash oder über einen Tree können die leider nicht.
 

jfkoernjf

Mitglied
Nein so einfach gehts denke ich nicht. Contains geht auf equals und hashcode (jetzt habe ich wieder Vor und Nachnamen).
Übrigens- wenn contains gehen würde, dann könnte ich auch ein Set nehmen :)
 
S

SlaterB

Gast
ein Set mit intelligenter Implementierung, etwa funktionieren Hash-Werten + HashSet, wäre in jedem Fall schneller als in der Liste zu prüfen,
ob man das später macht oder gleich beim Einfügen, ist da zweitrangig

bei Liste kann gerade noch Sortierung vom ärgsten quadratischen Aufwand auf n log n senken, das Set ist im Idealfall linear schnell
 
B

bygones

Gast
Reden wir hier von zwei unterschiedlichen Anforderungen ?

wenn nicht versteh ich nicht was genau das problem ist
Bis hier ist es für mich noch ganz klar- einfach ein Set nehmen, equals und hashCode in der Klasse überschreiben und dann mit addAll() hinzufügen
du schreibst selbst, per equals / hashCode kannst du dein Set manipulieren. Wenn du nun nur eine Person einer Familie haben willst passe deine equals/hashCode an.
 

Marco13

Top Contributor
Das Problem dürfte/könnte sein, dass man üblicherweise zwei Personen ("Hans Müller" und "Anne Müller") NICHT als equals ansehen will - und nur für diesen zweck eine equals/hashCode zu schreiben, die sich ansonsten "falsch" verhält, geht eben nicht.

Wenn es nur EIN Kriterium ist, nach dem die "Gleichheit" entschieden werden sollte, könnte man einfach sowas machen wie
Java:
        Map<String, Person> map = new LinkedHashMap<String, Person>();
        for (Person p : input)
        {
            map.put(p.getFirst(), p);
        }
        List<Person> output = new ArrayList<Person>(map.values());

Bei mehreren Kriterien könnte man einen ähnlichen Ansatz verwenden, aber statt 'String' for den Key eben sowas verwenden wie
new PersonID(person)
und bei PersonID dann die relevanten Sachen aus der Person rausholen und in einer dort implementierten equals/hashCode passend verwursten.
 

jfkoernjf

Mitglied
Genau so wies Marco verstanden hat, habe ich es gemeint. :)
Die equals-Methode in der Klasse Person wollte ich nicht anfassen, da ich ja nur an einer Stelle die Duplikate entfernen möchte. An einer anderen Stelle sind Anne Müller und Peter Müller natürlich unterschiedliche Personen.

Die Frage ist jetzt, ob die for-Schleife wie Marco sie gezeigt hat wirklich die schnellste und einfachste Möglichkeit ist, die Duplikate zu entfernen - sie funktioniert ja so ähnlich wie die, die ich zu Beginn erwähnt habe. Gerade bei Reports oder anderen Übersichten, wo Daten zusammengefasst werden müssen, habe ich bis jetzt solche Konstrukte immer wieder schreiben müssen.

Warum gibt es eigentlich kein Objekt, in dem ich equals und HashCode definierenkann? Dieses Objekt könnte ich dann einem Set mitgeben und gut ist. Beim Comparator geht das doch analog mit compareTo auch?
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ja, mit einer leicht "funktionalen" Anhauchung könnte man SEHR vieles (speziell auch, aber nicht nur in den Collections-Klassen) SEHR viel eleganter und allgemeingültiger machen. Gibt's aber erstmal nicht. Damit muss man entweder leben, oder man schreibt es sich selbst. Da kann man beliebig weit gehen um dann bei Functional Java zu landen, oder man schreibt sich was spezielles für den konkreten Fall selbst .
Java:
class FunctionalHashSet<T> implements Set<T>
{
    public FunctionalHashSet(UnaryFunction<T, Integer> hashFunction, BinaryFunction<T,T,Boolean> equality) 
    {
        ...
    }
}
Und los :)


EDIT: Hey, ich glaube, das wäre gar nicht sooo aufwändig...?! Bei Gelegenheit mal schauen :reflect:
 
B

...ButAlive

Gast
Ich würde das mit Comparator und TreeSet machen. Das sieht dann so aus:

Person.java
Java:
package person;

public class Person
{
	private final String vorname;
	private final String nachname;
	
	public Person(String vorname, String nachname)
	{
		this.vorname = vorname;
		this.nachname = nachname;
	}
	
	public String getNachname()
	{
		return nachname;
	}
	
	public String getVorname()
	{
		return vorname;
	}
	
	@Override
	public String toString()
	{
		return vorname+" "+nachname;
	}
}

PersonenComparator.java
Java:
package person;

import java.util.Comparator;

public class PersonComparator
	implements Comparator<Person>
{
	@Override
	public int compare(Person o1, Person o2)
	{
		return o1.getNachname().compareTo(o2.getNachname());
	}
}

PersonenTest.java
Java:
package person;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class PersonenTest
{
	public static void main(String[] args)
	{
		Person p1 = new Person("Hans", "Meier");
		Person p2 = new Person("Hans", "Müller");
		Person p3 = new Person("Erna", "Müller");
		
		List<Person> personenList = Arrays.asList(p1,p2,p3);
		
		PersonComparator personenComperator = new PersonComparator();
		Set<Person> personenSet = new TreeSet<Person>(personenComperator);
		personenSet.addAll(personenList);
		
		for (Person person : personenSet)
		{
			System.out.println(person);
		}		
	}
}
 

Marco13

Top Contributor
Ja, das ist die einfache Lösung, aber ... nicht die sicherste. Ein Comparator für eine SortedSet sollte "consistent with equals" sein, wie hier beschrieben: Comparator (Java Platform SE 6) - Der dort beschriebene Fall leuchtet ein, trifft aber auf dieses Beispiel nicht zu - und zugegeben: Ich habe gerade mal versucht, diese TreeMap "richtig kaputt" zu machen, aber es nicht geschafft. Trotzdem kann durch sowas ein Verhalten entstehen, das von der Spezifikation abweicht und viel Verwirrung stiftet: In deinem Fall würde für
personenSet.contains(p3)
noch 'true' zurückgegeben, aber der Eintrag ist gar nicht vorhanden... Es könnte "immer" funktionieren, aber letztendlich hängt es wohl von der Implementierung von TreeSet ab...
 

jfkoernjf

Mitglied
Ahh- jetzt geht die Diskussion in die richtige Richtung :)

Ist schon blöd, dass man für solche einfache Dinge redundanten Code schreiben muss.
Oder sich umständlich was bauen soll.

@Marco: Danke für den Link- habe von Functional Java noch nichts gehört- werde ich mir mal anschauen.
Auch wenn ich wahrscheinlich bei meiner for-Schleife bleiben werde :)

@ButAlive: Die Idee mit dem Comparator war gut- leider hat sie mir Marco madig geredet :-D
 
B

...ButAlive

Gast
Natürlich hat Marco13 recht wenn er mich auf die Java-API verweißt, aber sein Vorschlag verstößt genauso gegen den Vertrag von Set, denn da steht:

More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.
java.util.Set

Aber so eng würde ich dass nicht sehen. Bei meinem Vorschlag du bist halt dann auf TreeSet festgelegt, kannst nicht einfach gegen Set programmieren und beliebig die Implementierung austauschen. Bei Marco13 gilt das gleiche nur für FunctionalHashSet.

Ich würde das wahrscheinlich so verpacken:

Java:
public List<Person> filter(List<Person> personen)
{
        PersonComparator personenComperator = new PersonComparator();
        TreeSet<Person> personenSet = new TreeSet<Person>(personenComperator);
        personenSet.addAll(personen);
        List<Person> result = new ArrayList<Person>(personenSet);
        return result.
}

Dann hätte man dieses Problem zentriert und würde außerhalb mit einer List<Person> arbeiten.

Wenn man sich streng an die API halten will, gefällt mir Marco13s Vorschlag mit der Map am besten.
 
B

...ButAlive

Gast
Natürlich hat Marco13 recht wenn er mich auf die Java-API verweißt, aber sein Vorschlag verstößt genauso gegen den Vertrag von Set, denn da steht:

More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.
java.util.Set

Aber so eng würde ich dass nicht sehen. Bei meinem Vorschlag du bist halt dann auf TreeSet festgelegt, kannst nicht einfach gegen Set programmieren und beliebig die Implementierung austauschen. Bei Marco13 gilt das gleiche nur für FunctionalHashSet.

Ich würde das wahrscheinlich so verpacken:

Java:
public List<Person> filter(List<Person> personen)
{
        PersonComparator personenComperator = new PersonComparator();
        TreeSet<Person> personenSet = new TreeSet<Person>(personenComperator);
        personenSet.addAll(personen);
        List<Person> result = new ArrayList<Person>(personenSet);
        return result.
}

Dann hätte man dieses Problem zentriert und würde außerhalb mit einer List<Person> arbeiten.

Wenn man sich streng an die API halten will, gefällt mir Marco13s Vorschlag mit der Map am besten.
 

Marco13

Top Contributor
Bei meinem Vorschlagt könnte man das "implements Set<T>" einfach weglassen :D

Ich stimme dem, was du zuletzt gesagt hast, bedingt zu: Wenn man das NUR als kleine "Hilfsfunktion" verwendet
Java:
private /* !!! */ List<T> compute(List<T> input)
{
    List<T> output = doSomethingThatViolatesContracts();
    return output;
}
ist so eine Verletzung vielleicht nicht so schlimm. Das "kritische" daran ist, dass in der nächsten Java-Version vielleicht jemand eine Optimierung von TreeSet baut, die garantiert funktioniert, wenn man sich an die API-Spec hält - aber in diesem Fall würde es das mit dem Comparator vielleicht raushauen, mit Fehlern die man vielleicht erst zu spät bemerkt, und vor allem SEHR schwer aufspüren kann... Es ist einfach heikel... :bahnhof:
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
M Liste ohne Duplikate Java Basics - Anfänger-Themen 8
D Wie kann man in Java nach Arrays auf Duplikate prüfen Java Basics - Anfänger-Themen 12
G Java Objekte auf Duplikate testen Java Basics - Anfänger-Themen 4
M Duplikate in Array finden... Java Basics - Anfänger-Themen 9
G Exception und Ausgabe der Duplikate Java Basics - Anfänger-Themen 6
I Input/Output 3 Werte in Datei schreiben, duplikate vermeiden Java Basics - Anfänger-Themen 4
E Listen und Duplikate Java Basics - Anfänger-Themen 2
E Array untereinander auf Duplikate prüfen Java Basics - Anfänger-Themen 8
N Suche Technik um Wert-Duplikate auszuschließen Java Basics - Anfänger-Themen 3
0 Dynamische Datenstruktur ohne Duplikate und mit direkter Elementauswahl Java Basics - Anfänger-Themen 3
M Duplikate finden Java Basics - Anfänger-Themen 5
G Geht das effizienter?: Einlesen > Duplikate entf > Spe Java Basics - Anfänger-Themen 13
R Liste in Variable speichern Java Basics - Anfänger-Themen 6
R Liste und Arrays Java Basics - Anfänger-Themen 12
D 2 ArrayListen gleich sortieren bzw. eine Liste anhand einer anderen Sortieren Java Basics - Anfänger-Themen 6
J Ähnlichen String in Liste finden Java Basics - Anfänger-Themen 6
M Verkettete Liste Java Basics - Anfänger-Themen 1
M Vergleichen, ob eine Liste länger als andere ist Java Basics - Anfänger-Themen 6
H Liste nach String-Länge sortieren Java Basics - Anfänger-Themen 1
D remove Object von einer Liste von Obejcts Java Basics - Anfänger-Themen 3
E Elemente aus Liste entfernen und hinzufügen Java Basics - Anfänger-Themen 3
M Nullpointer beim befüllen meiner Liste im Object Java Basics - Anfänger-Themen 3
D Länge einer Liste aufrufen. Java Basics - Anfänger-Themen 19
B Objekt aus generalisierter Liste entfernen Java Basics - Anfänger-Themen 11
H Liste Knoten NullPointerException Java Basics - Anfänger-Themen 7
W Liste mit Listen in JTable darstellen Java Basics - Anfänger-Themen 1
N Was Passiert mit dem Namen einer Variable, wenn man diese einer Liste Hinzufügt Java Basics - Anfänger-Themen 16
E Suchfunktion in einer Liste Java Basics - Anfänger-Themen 39
T ungeordnete Werte-Paare in einer Liste Java Basics - Anfänger-Themen 7
L Hilfe! Liste mit Items werden ausgegeben aber nicht in zufälliger Reihenfolge Java Basics - Anfänger-Themen 6
berserkerdq2 Warum soll ich shuffle nutzen, um bei Rückgabewert Collection eine Liste zurückzugeben? Java Basics - Anfänger-Themen 3
sserio Wieso werden nicht alle Primzahlen bis 1000 in meine Liste gepackt ? Java Basics - Anfänger-Themen 8
sserio Liste erstellt und ein Problem mit dem Index Java Basics - Anfänger-Themen 8
f3mys Objektwerte in Liste speichern und wieder abrufen Java Basics - Anfänger-Themen 23
H Java verkettete Liste, Wert eines Index zurückgeben Java Basics - Anfänger-Themen 1
K Warum ist die binäre Suche bei der verketteten Liste nicht so effektiv? Java Basics - Anfänger-Themen 3
I 2D-Array Position der Liste ausgeben. Java Basics - Anfänger-Themen 2
I Liste von Infos von einer eigenen Annotation in Liste speichern Java Basics - Anfänger-Themen 0
P Doppelte werte in einer Liste zählen Java Basics - Anfänger-Themen 11
Dorfschmied Kartesisches Produkt von zwei Liste mit Hashmaps<String,String> erstellen Java Basics - Anfänger-Themen 4
Igig1 Autoparkplatz verkettete Liste erstes und letztes Auto Java Basics - Anfänger-Themen 13
thor_norsk Verkette Liste Java Basics - Anfänger-Themen 27
R Rückgabe: verkettete Liste Java Basics - Anfänger-Themen 2
R einfach verkettete Liste Java Basics - Anfänger-Themen 1
R einfach verkettete Liste Java Basics - Anfänger-Themen 12
O Doppelt verkette Liste Element löschen Java Basics - Anfänger-Themen 15
B GUI extension mit einer Liste verbinden Java Basics - Anfänger-Themen 1
B Verkettete Liste durchgehen und einzelne Elemente in neue Liste tun Java Basics - Anfänger-Themen 9
B Bin komplett am verzweifeln :( Verkettete Liste die Objekte hat Attribut auslesen Java Basics - Anfänger-Themen 14
M Java Liste streamen Java Basics - Anfänger-Themen 10
AmsananKING Aussortierung einer Liste Java Basics - Anfänger-Themen 8
A Objekte mit Parametern in eine Liste packen Java Basics - Anfänger-Themen 19
A Korrigierte <String> Liste zurückgeben Java Basics - Anfänger-Themen 22
S Kann nicht auf die Liste zugreifen mit der Methode!? Java Basics - Anfänger-Themen 3
B Datentyp für Einzelnes Objekt oder Liste Java Basics - Anfänger-Themen 9
alice98 Erste Schritte Liste erstellen ohne vorgefertigte Klassen Java Basics - Anfänger-Themen 1
J Doppelt verkette Liste ich bitte um Hilfe Java Basics - Anfänger-Themen 4
I Liste gruppieren nach Monat? Java Basics - Anfänger-Themen 5
districon Element in Liste einfügen Java Basics - Anfänger-Themen 1
B Hilfe bei Map Liste erstellen Java Basics - Anfänger-Themen 10
Y Einfügen in eine doppelt verkettete Liste Java Basics - Anfänger-Themen 8
Y Knoten an einem gegebenen Index aus einer Liste entfernen. Java Basics - Anfänger-Themen 6
H Daten aus einer Datei in eine Liste speichern Java Basics - Anfänger-Themen 23
Gaudimagspam Linked Liste Java Basics - Anfänger-Themen 4
Z Liste umkehren Java Basics - Anfänger-Themen 1
S Eine Liste kopieren Java Basics - Anfänger-Themen 13
java3690 Java- liste füllen ud die werte addieren Java Basics - Anfänger-Themen 13
java3690 Liste mit zufälligen zahlen füllen Java Basics - Anfänger-Themen 27
java3690 eine liste sortieren Java Basics - Anfänger-Themen 12
J Element aus Liste nehmen Java Basics - Anfänger-Themen 3
B JUnit 4: Wie man die eigene Liste testen kann [TDD] Java Basics - Anfänger-Themen 46
B Interface List - Objekt übergeben? Einzelnes Objekt geht, aber Liste nicht? Java Basics - Anfänger-Themen 4
P Was genau bringt mir es ein Array in eine Liste zu bringen Java Basics - Anfänger-Themen 3
A Doppelt verkettete Liste rückwärts ausgeben Java Basics - Anfänger-Themen 17
P Verschachtelte Array Liste Java Basics - Anfänger-Themen 2
H Liste speichern. Was lässt sich verbessern? Java Basics - Anfänger-Themen 7
P Performance Array und Liste Java Basics - Anfänger-Themen 13
M QuickSort und Liste Java Basics - Anfänger-Themen 6
N Methode um Objekte einer Liste hinzuzufügen Java Basics - Anfänger-Themen 1
B Summe von Property innerhalb einer Liste via Lambda Java Basics - Anfänger-Themen 1
V Collections int Werte in einer Liste sortieren Java Basics - Anfänger-Themen 23
B Neue Liste erstellen, wenn Objekte bestimmte Referenz hat / Gruppierung von Einträgen Java Basics - Anfänger-Themen 12
V_Fynn03 Beliebiges Element in einer Liste löschen (Java)(Lineare Datenstrukturen) Java Basics - Anfänger-Themen 9
L Baum aus Integer Liste erstellen Java Basics - Anfänger-Themen 0
CptK Koordinate in Liste suchen Java Basics - Anfänger-Themen 20
C Verschiedene Objekte in einer Liste speichern Java Basics - Anfänger-Themen 6
M Ausgabe einer Liste welche mehrere Stacks enthält Java Basics - Anfänger-Themen 3
D Doppelt Verkettete Zirkular-Liste Java Basics - Anfänger-Themen 1
L Liste in anderem Thread laden Java Basics - Anfänger-Themen 1
M Array liste Verdrehen Java Basics - Anfänger-Themen 8
A Verkettete Liste Java Basics - Anfänger-Themen 2
J Strings untereinander in einer Liste vergleichen Java Basics - Anfänger-Themen 18
B Liste von Tagen generieren ab einem bestimmten Datum und Endedatum Java Basics - Anfänger-Themen 4
S IndexOutOfBoundsException beim hinzufügen eines Elements zu einer Liste Java Basics - Anfänger-Themen 11
B Liste sortieren? Java Basics - Anfänger-Themen 4
O Anonyme Klasse einer Liste erstellen Java Basics - Anfänger-Themen 7
B SWAP List; Liste neu anordnen Java Basics - Anfänger-Themen 4
B CSS Klassen in eine Liste schreiben Java Basics - Anfänger-Themen 4
B Doppelt verkettete Liste implementieren Java Basics - Anfänger-Themen 8
L verkettete Liste Java Basics - Anfänger-Themen 15

Ähnliche Java Themen

Neue Themen


Oben