it-swarm.com.de

Wie entferne ich Duplikate aus einer Liste?

Ich möchte Duplikate aus einer Liste entfernen, aber was ich mache, funktioniert nicht:

List<Customer> listCustomer = new ArrayList<Customer>();    
for (Customer customer: tmpListCustomer)
{
  if (!listCustomer.contains(customer)) 
  {
    listCustomer.add(customer);
  }
 }
55
Mercer

Wenn dieser Code nicht funktioniert, haben Sie equals(Object) wahrscheinlich nicht ordnungsgemäß in der Customer-Klasse implementiert.

Vermutlich gibt es einen Schlüssel (nennen wir customerId), der einen Kunden eindeutig identifiziert. z.B.

class Customer {
    private String customerId;
    ...

Eine entsprechende Definition von equals(Object) würde folgendermaßen aussehen:

    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Customer)) {
            return false;
        }
        Customer other = (Customer) obj;
        return this.customerId.equals(other.customerId);
    }

Der Vollständigkeit halber sollte sollte auch hashCode implementieren, sodass zwei gleichwertige Customer-Objekte denselben Hashwert zurückgeben. Eine passende hashCode für die obige Definition von equals wäre:

    public int hashCode() {
        return customerId.hashCode();
    }

Es ist auch erwähnenswert, dass dies keine effiziente Methode zum Entfernen von Duplikaten ist, wenn die Liste groß ist. (Für eine Liste mit N Kunden müssen Sie im schlimmsten Fall N*(N-1)/2-Vergleiche durchführen; d. H., Wenn keine Duplikate vorhanden sind.) Für eine effizientere Lösung sollten Sie etwas wie eine HashSet für die Duplikatprüfung verwenden.

48
Stephen C

Angenommen, Sie möchten die aktuelle Bestellung behalten und keine Set.

List<Customer> depdupeCustomers =
    new ArrayList<>(new LinkedHashSet<>(customers));

Wenn Sie die ursprüngliche Liste ändern möchten:

Set<Customer> depdupeCustomers = new LinkedHashSet<>(customers);
customers.clear();
customers.addAll(dedupeCustomers);
88

Java 8 Update
Sie können den Array-Stream wie folgt verwenden: 

Arrays.stream(yourArray).distinct()
                    .collect(Collectors.toList());
25
Alireza Alallah

Implementiert der Kunde den equals()-Vertrag?

Wenn equals() und hashCode() nicht implementiert werden, prüft listCustomer.contains(customer), ob genau dieselbe Instanz bereits in der Liste vorhanden ist genau das gleiche Objekt - Speicheradresse usw.). Wenn Sie nach etwas suchen, um zu testen, ob derselbe Kunde ist oder nicht (vielleicht ist es derselbe Kunde, wenn er denselben Kundennamen oder dieselbe Kundennummer hat ) bereits in der Liste enthalten ist, müssten Sie equals() überschreiben, um sicherzustellen, dass überprüft wird, ob die relevanten Felder (z. B. Kundennamen) übereinstimmen.

Hinweis: Vergessen Sie nicht, hashCode() zu überschreiben, wenn Sie equals() überschreiben möchten! Andernfalls könnten Sie Probleme mit Ihren HashMaps und anderen Datenstrukturen bekommen. Sehen Sie sich die folgenden Kapitel von Josh Bloch an, um zu erfahren, warum dies so ist und welche Fallstricke zu vermeiden sind: Effektives Javaequals() und hashCode() (Der Link enthält nur Informationen darüber, warum Sie hashCode() bei der Implementierung implementieren müssen equals(), aber es gibt eine gute Abdeckung darüber, wie auch equals() außer Kraft gesetzt werden kann.

Gibt es übrigens eine Bestellbeschränkung für Ihr Set? Wenn dies nicht der Fall ist, können Sie dieses Problem leichter lösen, indem Sie einen Set<Customer> wie folgt verwenden:

Set<Customer> noDups = new HashSet<Customer>();
noDups.addAll(tmpListCustomer);
return new ArrayList<Customer>(noDups);

Das entfernt Duplikate für Sie, da Sets keine Duplikate zulassen. Die Reihenfolge, die auf tmpListCustomer angewendet wurde, geht jedoch verloren, da HashSet keine explizite Reihenfolge hat (Sie können dies umgehen, indem Sie TreeSet verwenden, aber das hängt nicht genau mit Ihrer Frage zusammen ). Dies kann Ihren Code ein wenig vereinfachen.

13
Scott Fines

Liste → Set → Liste (eindeutig)

Fügen Sie einfach alle Ihre Elemente zu einer Set hinzu: Sie können deren Elemente nicht wiederholen. Wenn Sie danach eine Liste benötigen, verwenden Sie anschließend den neuen ArrayList(theSet)-Konstruktor (wobei theSet Ihre Ergebnismenge ist).

13
folone

Ich vermute, Sie haben Customer.equals() möglicherweise nicht richtig (oder überhaupt nicht) implementiert.

List.contains() verwendet equals(), um zu überprüfen, ob eines seiner Elemente mit dem als Parameter übergebenen Objekt identisch ist. Die Standardimplementierung von equals prüft jedoch die physische Identität und nicht die Wertidentität. Wenn Sie es also nicht in Customer überschrieben haben, wird für zwei verschiedene Customer-Objekte mit gleichem Status false zurückgegeben.

Hier sind die winzigsten Details von wie man equals implementiert (und hashCode , das ist das Paar - Sie müssen beides praktisch immer implementieren, wenn Sie eines von beiden implementieren müssen). Da Sie uns die Kundenklasse nicht gezeigt haben, ist es schwierig, konkrete Ratschläge zu geben.

Wie andere bereits bemerkt haben, ist es besser, ein Set zu verwenden, als die Arbeit von Hand zu erledigen, aber selbst dafür müssen Sie diese Methoden implementieren.

9
Péter Török

Die "Enthält" -Methode hat gesucht, ob die Liste einen Eintrag enthält, der true von Customer.equals (Object o) zurückgibt. Wenn Sie in Customer oder einem seiner übergeordneten Objekt nicht gleich (Objekt) überschrieben haben, wird nur nach einem vorhandenen Vorkommen des gleichen Objekts gesucht. Möglicherweise haben Sie dies gewünscht. In diesem Fall sollte Ihr Code funktionieren. Wenn Sie jedoch nicht nach zwei Objekten suchten, die denselben Kunden repräsentieren, müssen Sie equals (Object) überschreiben, um wahr zurückzugeben, wenn dies der Fall ist. 

Es ist auch wahr, dass die Verwendung einer der Implementierungen von Set anstelle von List eine doppelte Entfernung automatisch und schneller (für alles andere als sehr kleine Listen) ermöglicht. Sie müssen immer noch Code für Gleichgestellte angeben.

Sie sollten auch hashCode () überschreiben, wenn Sie equals () überschreiben.

5
DJClayworth
private void removeTheDuplicates(List<Customer>myList) {
    for(ListIterator<Customer>iterator = myList.listIterator(); iterator.hasNext();) {
        Customer customer = iterator.next();
        if(Collections.frequency(myList, customer) > 1) {
            iterator.remove();
        }
    }
    System.out.println(myList.toString());

}
5
Bade

Fast alle der obigen Antworten sind richtig, aber ich schlage vor, beim Erstellen der Themenliste eine Map oder ein Set zu verwenden, nicht danach, um Leistung zu erzielen. Denn das Konvertieren einer Liste in einen Satz oder eine Karte und das erneute Umwandeln in eine Liste ist eine triviale Arbeit.

Beispielcode:

Set<String> stringsSet = new LinkedHashSet<String>();//A Linked hash set 
//prevents the adding order of the elements
for (String string: stringsList) {
    stringsSet.add(string);
}
return new ArrayList<String>(stringsSet);
3

Zwei Vorschläge:

  • Verwenden Sie ein HashSet anstelle einer ArrayList. Dies führt zu einer erheblichen Beschleunigung der enthaltenen () - Prüfungen, wenn Sie eine lange Liste haben

  • Stellen Sie sicher, dass Customer.equals () und Customer.hashCode () ordnungsgemäß implementiert sind, d. H. Sie sollten auf den kombinierten Werten der zugrunde liegenden Felder im Kundenobjekt basieren.

3
mikera

IMHO der beste Weg, wie es in diesen Tagen zu tun ist:

Angenommen, Sie haben eine Collection " dups " und möchten eine andere Collection erstellen, die dieselben Elemente enthält, jedoch alle Duplikate entfernt haben. Der folgende Einzeiler macht den Trick.

Collection<collectionType> noDups = new HashSet<collectionType>(dups);

Es erstellt ein Set, das per Definition keine Duplikate enthalten kann.

Basierend auf Oracle-Dokument.

1
Daniel Perník

Der sauberste Weg ist:

List<XXX> lstConsultada = dao.findByPropertyList(YYY);
List<XXX> lstFinal = new ArrayList<XXX>(new LinkedHashSet<GrupoOrigen>(XXX));

und überschreiben Sie hascode und equals über den Eigenschaften der Id jeder Entität

1
Eduardo

Wie andere bereits erwähnt haben, implementieren Sie equals () wahrscheinlich nicht korrekt.

Sie sollten jedoch auch beachten, dass dieser Code als ziemlich ineffizient betrachtet wird, da die Laufzeit die Anzahl der Elemente sein kann, die das Quadrat bilden.

Sie können stattdessen eine Satzstruktur anstelle einer Liste verwenden oder zuerst einen Satz erstellen und dann in eine Liste umwandeln.

1
Uri

Die richtige Antwort für Java ist ein Set . Wenn Sie bereits einen List<Customer> haben und ihn duplizieren möchten

Set<Customer> s = new HashSet<Customer>(listCustomer);

Verwenden Sie einfach eine Set-Implementierung HashSet, TreeSet und überspringen Sie die List-Konstruktionsphase.

Sie müssen hashCode() UND equals() in Ihren Domain-Klassen, die in der Variable Set abgelegt sind, überschreiben, um sicherzustellen, dass das gewünschte Verhalten tatsächlich das ist, was Sie erhalten. equals() kann so einfach sein wie der Vergleich eindeutiger IDs der Objekte mit einem so komplexen Vergleich wie jedes Feld. hashCode() kann so einfach sein wie das Zurückgeben der hashCode() der eindeutigen id 'String-Darstellung oder der hashCode().

0
user177800

Java 8 Stream API verwenden.

    List<String> list = new ArrayList<>();
    list.add("one");
    list.add("one");
    list.add("two");
    System.out.println(list);
    Collection<String> c = list.stream().collect(Collectors.toSet());
    System.out.println(c);

Ausgabe:

Vor Werten: [Eins, Eins, Zwei]

Nach Werten: [Eins, Zwei]

0
Kannan Msk