CodeGym/Java-Blog/Random-DE/Löschen eines Elements aus einer ArrayList
Autor
Volodymyr Portianko
Java Engineer at Playtika

Löschen eines Elements aus einer ArrayList

Veröffentlicht in der Gruppe Random-DE
Hallo! In der letzten Lektion haben wir uns mit der Klasse vertraut gemacht ArrayListund gelernt, wie man mit dieser Klasse die häufigsten Operationen durchführt. Darüber hinaus haben wir auf einige Unterschiede zwischen einem ArrayListund einem gewöhnlichen Array hingewiesen. Wir haben jedoch ein Thema umgangen, nämlich das Löschen von Elementen aus einer ArrayList. Das besprechen wir jetzt. Ein Element aus einer ArrayList löschen – 1Wir haben bereits erwähnt, dass das Löschen von Elementen aus einem gewöhnlichen Array nicht sehr praktisch ist. Da wir das Element selbst nicht löschen können, können wir nur seinen Wert „auf Null setzen“ (auf null setzen):
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public static void main(String[] args) {

       Cat[] cats = new Cat[3];
       cats[0] = new Cat("Thomas");
       cats[1] = new Cat("Behemoth");
       cats[2] = new Cat("Lionel Messi");

       cats[1] = null;

       System.out.println(Arrays.toString(cats));
   }


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Ausgabe: [Cat{name='Thomas'}, null, Cat{name='Lionel Messi'}] Aber das Setzen eines Array-Elements auf null hinterlässt ein „Loch“. Wir haben nicht die Position im Array entfernt, sondern nur seinen Inhalt. Stellen Sie sich vor, was passieren würde, wenn wir eine Gruppe von 50 Katzen hätten und 17 davon auf diese Weise entfernen würden. Wir werden ein Array mit 17 Löchern haben. Versuchen Sie einfach, den Überblick zu behalten! Es ist unrealistisch zu erwarten, dass Sie sich die Anzahl der leeren Zellen merken, in die Sie neue Werte schreiben können. Wenn Sie einen Fehler machen, überschreiben Sie eine gewünschte Objektreferenz. Es gibt natürlich eine Möglichkeit, dies etwas vorsichtiger zu machen: Nachdem Sie ein Element entfernt haben, verschieben Sie die Elemente an den Anfang des Arrays, um das „Loch“ am Ende zu platzieren:
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Behemoth");
   cats[2] = new Cat("Lionel Messi");
   cats[2] = new Cat("Fluffy");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       cats [i-1] = cats [i];// Move the elements to the front of the array, so the empty position is at the end
   }

   System.out.println(Arrays.toString(cats));
}
Ausgabe: [Cat{name='Thomas'}, Cat{name='Fluffy'}, Cat{name='Fluffy'}, null] Das scheint besser zu sein, kann aber kaum als robuste Lösung bezeichnet werden. Schon allein deshalb, weil wir diesen Code jedes Mal schreiben müssen, wenn wir ein Element aus einem Array löschen! Das ist eine schlechte Option. Wir könnten einen anderen Weg gehen und eine separate Methode erstellen:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...delete the cat corresponding to the index and move the elements
}
Aber auch das nützt wenig: Diese Methode kann nur mit Objekten funktionieren Cat, nicht aber mit anderen Typen. Mit anderen Worten: Wenn ein Programm weitere 100 Klassen hat, die wir mit Arrays verwenden möchten, müssen wir in jeder von ihnen dieselbe Methode mit genau derselben Logik schreiben. Das ist eine totale Katastrophe -_- Aber die ArrayListKlasse löst dieses Problem! Es implementiert eine spezielle Methode zum Entfernen von Elementen:remove()
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
Wir übergeben den Index unseres Objekts an die Methode, die es löscht (genau wie in einem Array). Die remove()Methode weist zwei Besonderheiten auf. Erstens hinterlässt es keine „Löcher“. Es implementiert bereits die Logik, die zum Verschieben von Elementen erforderlich ist, wenn ein Element aus der Mitte entfernt wird, die wir zuvor selbst geschrieben haben. Schauen Sie sich die Ausgabe des vorherigen Codes an:
[Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]

[Cat{name='Thomas'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}]
Wir haben eine Katze aus der Mitte entfernt und den Rest so verschoben, dass keine Leerstellen entstanden. Zweitens kann es Objekte nicht nur nach Index löschen (wie ein normales Array), sondern auch nach Referenz :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);
   System.out.println(cats.toString());

   cats.remove(lionel);

   System.out.println(cats.toString());
}
Ausgabe: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Lionel Messi'}, Cat{name='Fluffy'}] [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Dies kann sehr praktisch sein, wenn Sie nicht immer den Index des gewünschten Objekts im Auge behalten möchten. Anscheinend haben wir herausgefunden, wie man ganz normal löscht. Stellen wir uns nun diese Situation vor: Wir möchten unsere Liste durchlaufen und eine Katze mit einem bestimmten Namen entfernen . Dazu verwenden wir eine schnelle forSchleife (auch for-each-Schleife genannt), die wir in Rishis Lektionen kennengelernt haben:
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Behemoth");
   Cat lionel = new Cat("Lionel Messi");
   Cat fluffy = new Cat ("Fluffy");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(lionel);
   cats.add(fluffy);

   for (Cat cat: cats) {

       if (cat.name.equals("Behemoth")) {
           cats.remove(cat);
       }
   }

   System.out.println(cats);
}
Der Code sieht vollkommen logisch aus. Aber das Ergebnis könnte eine große Überraschung sein: Ausnahme im Thread „main“ java.util.ConcurrentModificationException bei java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) bei java.util.ArrayList$Itr.next(ArrayList. java:831) bei Cat.main(Cat.java:25) Es liegt ein Fehler vor und es ist unklar, warum er aufgetreten ist. Dieser Prozess beinhaltet eine Reihe von Nuancen, die berücksichtigt werden müssen. Hier ist die allgemeine Regel, die Sie beachten müssen: Sie können eine Sammlung nicht gleichzeitig durchlaufen und ihre Elemente ändern. Und wir meinen jede Art von Veränderung, nicht nur die Entfernung. Wenn Sie die Katzenentfernung durch den Versuch ersetzen, neue Katzen einzusetzen, ist das Ergebnis dasselbe:
for (Cat cat: cats) {

   cats.add(new Cat("Salem Saberhagen"));
}

System.out.println(cats);
Ausnahme im Thread „main“ java.util.ConcurrentModificationException bei java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859) bei java.util.ArrayList$Itr.next(ArrayList.java:831) bei Cat.main( Cat.java:25) Wir haben eine Operation in eine andere geändert, aber das Ergebnis hat sich nicht geändert: Wir erhalten die gleiche ConcurrentModificationException . Es tritt genau dann auf, wenn wir versuchen, die obige Regel zu brechen, indem wir die Liste ändern, während wir darüber iterieren. In Java benötigen wir ein spezielles Objekt namens Iterator (IteratorKlasse), um Elemente beim Durchlaufen einer Sammlung zu löschen. DieIteratorKlasse ist dafür verantwortlich, die Liste der Elemente sicher zu durchlaufen. Es ist ganz einfach, da es nur drei Methoden gibt:
  • hasNext()- gibt true oder false zurück, je nachdem, ob es ein nächstes Element in der Liste gibt oder wir bereits beim letzten Element angekommen sind.
  • next()– gibt das nächste Element in der Liste zurück
  • remove()– Entfernt ein Element aus der Liste
Wie Sie sehen, ist der Iterator auf unsere Bedürfnisse zugeschnitten und gleichzeitig nichts Kompliziertes daran. Angenommen, wir möchten prüfen, ob ein nächstes Element in unserer Liste vorhanden ist, und es anzeigen, wenn Folgendes vorhanden ist:
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   System.out.println(nextCat);// Display it
}
Ausgabe: Cat{name='Thomas'} Cat{name='Behemoth'} Cat{name='Lionel Messi'} Cat{name='Fluffy'} Wie Sie sehen können, hat das bereits eine spezielle Methode ArrayListzum Erstellen eines implementiert Iterator: iterator(). Beachten Sie außerdem, dass wir beim Erstellen eines Iterators die Objektklasse angeben, mit der er arbeiten soll ( <Cat>). Das Fazit ist, dass ein Iterator unsere ursprüngliche Aufgabe problemlos bewältigen kann. Entfernen Sie beispielsweise die Katze namens „Lionel Messi“:
Iterator<Cat> catIterator = cats.iterator();// Create an iterator
while(catIterator.hasNext()) {// As long as there are elements in the list

   Cat nextCat = catIterator.next();// Get the next element
   if (nextCat.name.equals("Lionel Messi")) {
       catIterator.remove();// Delete the cat with the specified name
   }
}

System.out.println(cats);
Ausgabe: [Cat{name='Thomas'}, Cat{name='Behemoth'}, Cat{name='Fluffy'}] Möglicherweise ist Ihnen aufgefallen, dass wir in der remove()Methode des Iterators weder den Index noch den Namen angegeben haben ! Der Iterator ist intelligenter, als es den Anschein macht: remove()Er entfernt das letzte vom Iterator zurückgegebene Element. Wie Sie sehen, hat es genau das getan, was wir wollten :) Im Prinzip ist dies alles, was Sie über das Entfernen von Elementen aus einer . wissen müssen ArrayList. Na ja, fast alles. In der nächsten Lektion werfen wir einen Blick in diese Klasse und sehen, was dort bei verschiedenen Methodenaufrufen passiert :) Bis dahin!
Kommentare
  • Beliebt
  • Neu
  • Alt
Du musst angemeldet sein, um einen Kommentar schreiben zu können
Auf dieser Seite gibt es noch keine Kommentare