Doppelte Datensätze aus ArrayList entfernen: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
K
K
 
(31 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
Manchmal hat man Listen mit doppelten oder mehrfachen Einträgen. Wenn man keine doppelten Einträge in einer {{JAPI|Collection}} zulassen möchte, verwendet man statt einer {{JAPI|List}} ein {{JAPI|Set}}. Sets lassen von Hause aus keine doppelten Einträge zu. Dieses Verhalten kann man zur Lösung des Problems dieses Themas benutzen.
+
Manchmal hat man Listen mit doppelten oder mehrfachen Einträgen.  
  
{{In Arbeit}}
+
Eine Beispielausgabe einer solchen Liste:
 +
1 100 abc def 10 1 200 def 1000 def ghi 10 0
 +
 
 +
Um nun Duplikate aus Listen zu entfernen, müssen primitive [[Variable|Variablen]] oder Objekte verglichen werden.
 +
 
 +
'''Sollen [[Objekt|Objekte]] auf Gleichheit geprüft werden, muss die [[==, equals() und Identität und Gleichheit|equals()-Methode]] sinnvoll überschrieben werden.'''
 +
 
 +
==Lösung durch Umwandlung==
 +
 
 +
Wenn man keine Duplikate in einer {{JAPI|Collection}} zulassen möchte, verwendet man statt einer {{JAPI|List}} ein {{JAPI|Set}}.
 +
 
 +
Sets lassen von Hause aus keine doppelten Einträge zu. Dieses Verhalten kann man zur Lösung des Problems dieses Themas benutzen.
 +
 
 +
Folgende fertige Klasse kann in eigenen Programmen zur Anwendung kommen. Es genügt also, die Klasse in Ihr Programm einzubinden und eine oder ggf. mehrere Methoden aufzurufen.
 +
 
 +
<syntaxhighlight lang="java">
 +
package net.byte_welt.util;
 +
 
 +
import java.util.ArrayList;
 +
import java.util.LinkedHashSet;
 +
import java.util.Iterator;
 +
import java.util.List;
 +
import java.util.Set;
  
<code=java>
 
 
/**
 
/**
 
  * CollectionUtil bietet Methoden zur Umwandlung und Behandlung von
 
  * CollectionUtil bietet Methoden zur Umwandlung und Behandlung von
Zeile 20: Zeile 41:
 
   public static List<?> removeDuplicate(List<?> list) {
 
   public static List<?> removeDuplicate(List<?> list) {
 
       Set<?> set = transformListIntoSet(list);
 
       Set<?> set = transformListIntoSet(list);
       List<?> listWithoutDuplicate = transformSetIntoList(set);
+
       return transformSetIntoList(set);
      return listWithoutDuplicate;
 
 
   }
 
   }
  
 
   /**
 
   /**
     * Wandelt eine List in ein Set um.
+
     * Wandelt eine List in ein Set um. Die Reihenfolge der Objekte
 +
    * in der Liste bleibt dabei auch im Set erhalten.
 
     *
 
     *
 
     * @param list die Liste, die in ein Set verwandelt werden soll
 
     * @param list die Liste, die in ein Set verwandelt werden soll
Zeile 31: Zeile 52:
 
     */
 
     */
 
   public static Set<?> transformListIntoSet(List<?> list) {
 
   public static Set<?> transformListIntoSet(List<?> list) {
       Set<?> set = new HashSet<>();
+
       Set<Object> set = new LinkedHashSet<>();
       for(Object o : list) {
+
       set.addAll(list);
        set.put(o);
 
      }
 
 
       return set;
 
       return set;
 
   }
 
   }
Zeile 45: Zeile 64:
 
     */
 
     */
 
   public static List<?> transformSetIntoList(Set<?> set) {
 
   public static List<?> transformSetIntoList(Set<?> set) {
       List<?> list = new ArrayList<>();
+
       List<Object> list = new ArrayList<>();
       Iterator<?> it = set.iterator();
+
       list.addAll(set);
      while(it.hasNext()) {
 
        list.add(it.next());
 
      }
 
 
       return list;
 
       return list;
 
   }
 
   }
 
 
 
}
 
}
</code=java>
+
</syntaxhighlight>
 +
 
 +
Binden Sie also die Klasse in Ihren Code ein und rufen zum Entfernen von Duplikaten aus einer Liste folgende Anweisungen auf:
 +
<syntaxhighlight lang="java">
 +
List<?> myList = [...]
 +
List<?> adjustedList = CollectionUtil.removeDuplicate(myList);
 +
System.out.println(Arrays.toString(adjustedList.toArray()));
 +
</syntaxhighlight>
 +
Führt man nun ein Programm aus, in welchem <code>CollectionUtil.removeDuplicate(myList)</code> aufgerufen wurde, erhalten wir bei Eingabe eingangs gezeigten Liste folgende bereinigte Ausgabe:
 +
1 100 abc def 10 200 1000 ghi 0
 +
==Lösung mit Schleifen==
 +
 
 +
Ganz ohne Umwandlung der Collection-Typen kann man auch folgende Methode beauftragen, nur je ein Exemplar mehrfach vertretener Objekte in der Liste zu belassen:
 +
<syntaxhighlight lang="java">
 +
  /**
 +
    * Behält nur je ein Exemplar mehrfach vertretener Objekte in der übergebenen Liste.
 +
    *
 +
    * @param list eine Liste mit doppelten/mehrfachen Objekt-Exemplaren
 +
    */
 +
  public static void removeDuplicate(List list) {
 +
      int size = list.size();
 +
      for(int i = 0; i < size; i++) {
 +
        Object o1 = list.get(i);
 +
        for(int j = i + 1; j < size; j++) {
 +
            Object o2 = list.get(j);
 +
            if(o1.equals(o2)) {
 +
              list.remove(j);
 +
              size--;
 +
            }
 +
        }
 +
      }
 +
  }
 +
</syntaxhighlight>
 +
 
 +
Manchmal möchte man aber auch Duplikate markieren, bspw. in einer [[JTable (Java API)|JTable]]. (In einem [[TableModel]] kann man diese Möglichkeit bereit stellen: [[Doppelte Datensätze aus ArrayList entfernen#TableModel zur Markierung von Duplikaten in einer JTable|TableModel zur Markierung von Duplikaten in einer JTable]])
 +
 
 +
...oder gänzlich entfernen, so dass es keine Objekte in einer Liste mehr gibt, die zu Duplikaten geführt haben.
 +
 
 +
==Alle doppelten Objekte aus einer Liste entfernen==
 +
 
 +
<syntaxhighlight lang="java">
 +
[import ...]
 +
import java.util.HashSet;
 +
 
 +
[...]
 +
 
 +
 
 +
  /**
 +
    * Entfernt doppelte Einträge aus der übergebenen Liste.
 +
    * Es werden alle Objekte entfernt, die zu Duplikaten geführt haben.
 +
    *
 +
    * @param list eine Liste mit doppelten Einträgen
 +
    * @return die um alle doppelten Einträge bereinigte Liste
 +
    */
 +
  public static void removeAllDuplicate(List<?> list) {
 +
      Set<Integer> duplicateSet = new HashSet<>();
 +
 
 +
      for(int i = 0, j = list.size(); i < j; i++) { //komplette Liste durchlaufen
 +
        Object o1 = list.get(i);                  //Objekt an Index-Position holen
 +
        for (int x = i + 1; x < j; x++) {          //Folgeeinträge durchlaufen
 +
            Object o2 = list.get(x);
 +
            if (o1.equals(o2)) {                    //Bei Objektidentität deren Indizes im Set ablegen
 +
                duplicateSet.add(i);
 +
                duplicateSet.add(x);
 +
            }
 +
        }
 +
      }
 +
 
 +
      List<Integer> indexList = new ArrayList<>(duplicateSet);
 +
      Collections.sort(indexList);                  //Liste nach Indizes sortieren
 +
      Collections.reverse(indexList);              //größte Indizes zuerst in der Liste
 +
      for(int i : indexList) {
 +
            list.remove(i);                        //Objekte aus Liste "von hinten nach vorne" löschen
 +
      }
 +
  }
 +
</syntaxhighlight>
 +
 
 +
Und wieder testen wir die eingangs gezeigte Liste und bekommen folgende Ausgabe:
 +
100 abc 200 1000 ghi 0
 +
 
 +
=TableModel zur Markierung von Duplikaten in einer JTable=
 +
 
 +
Wie oben schon angeschnitten, kann man die oben gezeigten Code-Stücke dazu verwenden, um in einer [[Duplikate in einer JTable markieren|JTable Duplikate zu markieren]], die in einem [[TableModel (Java API)]] gespeichert sind.
 +
 
 +
{{Fragen stellen}}
  
[[Kategorie:Java]]
+
[[Kategorie:Tutorials (Java)]]
 
[[Kategorie:Java-Codeschnipsel]]
 
[[Kategorie:Java-Codeschnipsel]]

Aktuelle Version vom 3. Februar 2022, 12:21 Uhr

Manchmal hat man Listen mit doppelten oder mehrfachen Einträgen.

Eine Beispielausgabe einer solchen Liste:

1 100 abc def 10 1 200 def 1000 def ghi 10 0 

Um nun Duplikate aus Listen zu entfernen, müssen primitive Variablen oder Objekte verglichen werden.

Sollen Objekte auf Gleichheit geprüft werden, muss die equals()-Methode sinnvoll überschrieben werden.

Lösung durch Umwandlung

Wenn man keine Duplikate in einer Collection zulassen möchte, verwendet man statt einer List ein Set.

Sets lassen von Hause aus keine doppelten Einträge zu. Dieses Verhalten kann man zur Lösung des Problems dieses Themas benutzen.

Folgende fertige Klasse kann in eigenen Programmen zur Anwendung kommen. Es genügt also, die Klasse in Ihr Programm einzubinden und eine oder ggf. mehrere Methoden aufzurufen.

package net.byte_welt.util;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

/**
 * CollectionUtil bietet Methoden zur Umwandlung und Behandlung von
 * Collection-Typen an.
 *
 * @autor Gernot Segieth
 */
public class CollectionUtil {

   /**
    * Entfernt doppelte Einträge aus der übergebenen Liste.
    *
    * @param list eine Liste mit doppelten Einträgen
    * @return die um doppelte Einträge bereinigte Liste
    */
   public static List<?> removeDuplicate(List<?> list) {
      Set<?> set = transformListIntoSet(list);
      return transformSetIntoList(set);
   }

   /**
    * Wandelt eine List in ein Set um. Die Reihenfolge der Objekte
    * in der Liste bleibt dabei auch im Set erhalten.
    *
    * @param list die Liste, die in ein Set verwandelt werden soll
    * @return der Ergebnis-Typ, ein Set
    */
   public static Set<?> transformListIntoSet(List<?> list) {
      Set<Object> set = new LinkedHashSet<>();
      set.addAll(list);
      return set;
   }

   /**
    * Wandelt ein Set in eine List um.
    *
    * @param set das Set, das in eine List verwandelt werden soll
    * @return der Ergebnis-Typ, eine List
    */
   public static List<?> transformSetIntoList(Set<?> set) {
      List<Object> list = new ArrayList<>();
      list.addAll(set);
      return list;
   }
}

Binden Sie also die Klasse in Ihren Code ein und rufen zum Entfernen von Duplikaten aus einer Liste folgende Anweisungen auf:

List<?> myList = [...]
List<?> adjustedList = CollectionUtil.removeDuplicate(myList);
System.out.println(Arrays.toString(adjustedList.toArray()));

Führt man nun ein Programm aus, in welchem CollectionUtil.removeDuplicate(myList) aufgerufen wurde, erhalten wir bei Eingabe eingangs gezeigten Liste folgende bereinigte Ausgabe:

1 100 abc def 10 200 1000 ghi 0 

Lösung mit Schleifen

Ganz ohne Umwandlung der Collection-Typen kann man auch folgende Methode beauftragen, nur je ein Exemplar mehrfach vertretener Objekte in der Liste zu belassen:

   /**
    * Behält nur je ein Exemplar mehrfach vertretener Objekte in der übergebenen Liste.
    *
    * @param list eine Liste mit doppelten/mehrfachen Objekt-Exemplaren
    */
   public static void removeDuplicate(List list) {
      int size = list.size();
      for(int i = 0; i < size; i++) {
         Object o1 = list.get(i);
         for(int j = i + 1; j < size; j++) {
            Object o2 = list.get(j);
            if(o1.equals(o2)) {
               list.remove(j);
               size--;
            }
         }
      }
   }

Manchmal möchte man aber auch Duplikate markieren, bspw. in einer JTable. (In einem TableModel kann man diese Möglichkeit bereit stellen: TableModel zur Markierung von Duplikaten in einer JTable)

...oder gänzlich entfernen, so dass es keine Objekte in einer Liste mehr gibt, die zu Duplikaten geführt haben.

Alle doppelten Objekte aus einer Liste entfernen

[import ...]
import java.util.HashSet;

[...]


   /**
    * Entfernt doppelte Einträge aus der übergebenen Liste.
    * Es werden alle Objekte entfernt, die zu Duplikaten geführt haben.
    *
    * @param list eine Liste mit doppelten Einträgen
    * @return die um alle doppelten Einträge bereinigte Liste
    */
   public static void removeAllDuplicate(List<?> list) {
      Set<Integer> duplicateSet = new HashSet<>();

      for(int i = 0, j = list.size(); i < j; i++) { //komplette Liste durchlaufen
         Object o1 = list.get(i);                   //Objekt an Index-Position holen
         for (int x = i + 1; x < j; x++) {          //Folgeeinträge durchlaufen
            Object o2 = list.get(x);
            if (o1.equals(o2)) {                    //Bei Objektidentität deren Indizes im Set ablegen
                duplicateSet.add(i);
                duplicateSet.add(x);
            }
         }
      }

      List<Integer> indexList = new ArrayList<>(duplicateSet);
      Collections.sort(indexList);                  //Liste nach Indizes sortieren
      Collections.reverse(indexList);               //größte Indizes zuerst in der Liste
      for(int i : indexList) { 
            list.remove(i);                         //Objekte aus Liste "von hinten nach vorne" löschen
      }
   }

Und wieder testen wir die eingangs gezeigte Liste und bekommen folgende Ausgabe:

100 abc 200 1000 ghi 0

TableModel zur Markierung von Duplikaten in einer JTable

Wie oben schon angeschnitten, kann man die oben gezeigten Code-Stücke dazu verwenden, um in einer JTable Duplikate zu markieren, die in einem TableModel (Java API) gespeichert sind.


Fragen

Das Thema wurde nicht ausreichend behandelt? Du hast Fragen dazu und brauchst weitere Informationen? Lass Dir von uns helfen!

Wir helfen dir gerne!


Dir hat dieser Artikel gefallen? Oder Du hast Fehler entdeckt und möchtest zur Berichtigung beitragen? Prima! Schreibe einen Kommentar!

Du musst angemeldet sein, um einen Kommentar abzugeben.