JavaRush /Java-Blog /Random-DE /Entfernen eines Elements aus einer ArrayList in Java

Entfernen eines Elements aus einer ArrayList in Java

Veröffentlicht in der Gruppe Random-DE
Hallo! In der letzten Vorlesung haben wir uns mit der Klasse ArrayList vertraut gemacht und auch gelernt, wie man damit die gängigsten Operationen durchführt. Darüber hinaus haben wir einige Unterschiede zwischen ArrayList und einem regulären Array hervorgehoben. Schauen wir uns nun das Entfernen eines Elements aus der ArrayList an. Wir haben bereits gesagt, dass das Löschen von Elementen in einem regulären Array nicht sehr praktisch ist. Entfernen eines Elements aus einer ArrayList - 1Da wir die Zelle selbst nicht löschen können, können wir ihren Wert nur 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("Nilpferd");
       cats[2] = new Cat(„Philip Markowitsch“);

       cats[1] = null;

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


@Override
   public String toString() {
       return "Cat{" +
               "name='" + name + '\'' +
               '}';
   }
}
Abschluss:

[Cat{name='Томас'}, null, Cat{name='Фoderпп Маркович'}]
Beim Zurücksetzen bleibt jedoch ein „Loch“ im Array. Wir löschen nicht die Zelle, sondern nur ihren Inhalt. Stellen Sie sich vor, was passieren würde, wenn wir ein Array von 50 Katzen hätten, von denen wir 17 auf diese Weise gelöscht hätten. Wir werden ein Feld mit 17 Löchern haben und uns um sie kümmern! Es ist unrealistisch, sich die Anzahl der leeren Zellen auswendig zu merken, in die Sie neue Werte schreiben können. Machen Sie einmal einen Fehler und Sie überschreiben die Zelle mit dem gewünschten Verweis auf das Objekt. Natürlich gibt es auch die Möglichkeit, etwas vorsichtiger vorzugehen: Verschieben Sie nach dem Löschen die Elemente des Arrays an den Anfang, sodass das „Loch“ am Ende ist:
public static void main(String[] args) {

   Cat[] cats = new Cat[4];
   cats[0] = new Cat("Thomas");
   cats[1] = new Cat("Nilpferd");
   cats[2] = new Cat(„Philip Markowitsch“);
   cats[3] = new Cat("Flaum");

   cats[1] = null;

   for (int i = 2; i < cats.length-1; i++) {
       //verschiebe die Elemente an den Anfang, sodass die leere Zelle am Ende liegt
       cats[i-1] = cats[i];
       cats[i] = null;
   }

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

[Cat{name='Томас'}, Cat{name='Фoderпп Маркович'}, Cat{name='Пушок'}, null]
Jetzt scheint es besser auszusehen, aber von einer stabilen Lösung kann man kaum sprechen. Zumindest, weil wir diesen Code jedes Mal von Hand schreiben müssen, wenn wir ein Element aus dem Array entfernen! Schlechte Option. Sie könnten auch den anderen Weg gehen und eine separate Methode erstellen:
public void deleteCat(Cat[] cats, int indexToDelete) {
   //...die Katze nach Index entfernen und die Elemente verschieben
}
Aber auch das nützt wenig: Diese Methode kann nur mit Objekten arbeiten Cat, nicht aber mit anderen. Das heißt, wenn das Programm 100 weitere Klassen enthält, mit denen wir Arrays verwenden möchten, müssen wir in jeder von ihnen dieselbe Methode mit genau derselben Logik schreiben. Das ist ein völliger Fehlschlag -_- Aber in der ArrayList-Klasse wurde dieses Problem erfolgreich gelöst! 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("Nilpferd");
   Cat philipp = new Cat(„Philip Markowitsch“);
   Cat pushok = new Cat("Flaum");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(1);

   System.out.println(cats.toString());
}
Wir haben den Index unseres Objekts an die Methode übergeben und es wurde gelöscht (genau wie in einem Array). Die Methode remove()weist zwei Merkmale auf. Erstens hinterlässt es keine „Löcher“. Es implementiert bereits die Logik des Verschiebens von Elementen beim Entfernen eines Elements aus der Mitte, die wir zuvor von Hand geschrieben haben. Schauen Sie sich die Ausgabe des vorherigen Codes in der Konsole an:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фoderпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Фoderпп Маркович'}, Cat{name='Пушок'}]
Wir haben eine Katze aus der Mitte entfernt und die anderen so verschoben, dass keine Lücken entstanden. Zweitens kann ein Objekt nicht nur anhand des Index (wie ein reguläres Array), sondern auch anhand des Verweises auf das Objekt gelöscht werden :
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Nilpferd");
   Cat philipp = new Cat(„Philip Markowitsch“);
   Cat pushok = new Cat("Flaum");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);
   System.out.println(cats.toString());

   cats.remove(philipp);

   System.out.println(cats.toString());
}
Abschluss:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Фoderпп Маркович'}, Cat{name='Пушок'}]
[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Dies kann sehr praktisch sein, wenn Sie nicht immer den Index des gewünschten Objekts im Kopf behalten möchten. Wir scheinen die übliche Löschung geklärt zu haben. Stellen wir uns nun diese Situation vor: Wir möchten unsere Liste der Elemente durchlaufen und eine Katze mit einem bestimmten Namen entfernen. Dazu verwenden wir einen speziellen Schleifenoperator forfor each. Mehr dazu erfahren Sie in diesem Vortrag .
public static void main(String[] args) {

   ArrayList<Cat> cats = new ArrayList<>();
   Cat thomas = new Cat("Thomas");
   Cat behemoth = new Cat("Nilpferd");
   Cat philipp = new Cat(„Philip Markowitsch“);
   Cat pushok = new Cat("Flaum");

   cats.add(thomas);
   cats.add(behemoth);
   cats.add(philipp);
   cats.add(pushok);

   for (Cat cat: cats) {

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

   System.out.println(cats);
}
Der Code scheint ziemlich logisch zu sein. Das Ergebnis könnte Sie jedoch überraschen:

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
Irgendein Fehler, und es ist unklar, warum er plötzlich auftrat. In diesem Prozess gibt es eine Reihe von Nuancen, die berücksichtigt werden müssen. Eine allgemeine Regel, die Sie beachten müssen: Sie können eine Sammlung nicht durchlaufen und gleichzeitig ihre Elemente ändern. Ja, ja, genau eine Änderung und nicht nur eine Streichung. Wenn Sie in unserem Code versuchen, das Entfernen von Katzen durch das Einfügen neuer zu ersetzen, ist das Ergebnis dasselbe:
for (Cat cat: cats) {

   cats.add(new Cat(„Salem Saberhegen“));
}

System.out.println(cats);

Exception in thread "main" java.util.ConcurrentModificationException
  at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
  at java.util.ArrayList$Itr.next(ArrayList.java:831)
  at Cat.main(Cat.java:25)
Wir haben einen Vorgang in einen anderen geändert, aber das Ergebnis hat sich nicht geändert: der gleiche Fehler ConcurrentModificationException. Es tritt genau dann auf, wenn wir versuchen, eine Regel zu brechen und die Liste zu ändern, während wir sie durchlaufen. Um in Java Elemente während der Iteration zu entfernen, müssen Sie ein spezielles Objekt verwenden – einen Iterator (Klasse Iterator). Die Klasse Iteratorist dafür verantwortlich, eine Liste von Elementen sicher durchzugehen. Es ist ganz einfach, da es nur drei Methoden gibt:
  • hasNext()- gibt trueentweder falseabhängig davon zurück, ob es ein nächstes Element in der Liste gibt oder ob wir bereits beim letzten Element angekommen sind.
  • next()- gibt das nächste Element der Liste zurück
  • remove()- Entfernt ein Element aus der Liste
Wie Sie sehen, ist der Iterator buchstäblich auf unsere Bedürfnisse „zugeschnitten“ und nichts Kompliziertes daran. Wir möchten beispielsweise prüfen, ob unsere Liste das folgende Element enthält, und es in diesem Fall auf der Konsole ausgeben:
Iterator<Cat> catIterator = cats.iterator();//Erstelle einen Iterator
while(catIterator.hasNext()) {//solange es Elemente in der Liste gibt

   Cat nextCat = catIterator.next();//Nächstes Element abrufen
   System.out.println(nextCat);// Drucke es auf der Konsole aus
}
Abschluss:

Cat{name='Томас'}
Cat{name='Бегемот'}
Cat{name='Фoderпп Маркович'}
Cat{name='Пушок'}
Wie Sie sehen, ArrayListimplementiert die Klasse bereits eine spezielle Methode zum Erstellen eines Iterators – iterator(). Beachten Sie außerdem, dass wir beim Erstellen eines Iterators die Objektklasse angeben, mit der er arbeiten soll ( <Cat>). Letztendlich können wir unser ursprüngliches Problem einfach mithilfe eines Iterators lösen. Löschen wir zum Beispiel eine Katze namens „Philip Markovich“:
Iterator<Cat> catIterator = cats.iterator();//Erstelle einen Iterator
while(catIterator.hasNext()) {//solange es Elemente in der Liste gibt

   Cat nextCat = catIterator.next();//Nächstes Element abrufen
   if (nextCat.name.equals(„Philip Markowitsch“)) {
       catIterator.remove();//die Katze mit dem gewünschten Namen löschen
   }
}

System.out.println(cats);
Abschluss:

[Cat{name='Томас'}, Cat{name='Бегемот'}, Cat{name='Пушок'}]
Möglicherweise ist Ihnen aufgefallen, dass wir in der Iterator-Methode weder den Elementindex noch den Namen der Referenzvariablen angegeben haben remove()! Der Iterator ist intelligenter, als es den Anschein hat: Die Methode remove()entfernt das letzte Element, das vom Iterator zurückgegeben wurde. Wie Sie sehen, hat es genau nach Bedarf funktioniert :) Das ist im Grunde alles, was Sie über das Entfernen von Elementen aus wissen müssen ArrayList. Genauer gesagt: fast alles. In der nächsten Vorlesung schauen wir uns das „Innere“ dieser Klasse an und schauen, was dort im Betrieb passiert :) Wir sehen uns!
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION