Entfernen von Elementen aus Java-Sammlungen

Elemente aus Java-Sammlungen entfernen

1. Überblick

In diesem kurzen Tutorial werdenwe’re going to talk about four different ways to remove items from Java Collections that match certain predicates.

Wir werden uns natürlich auch einige der Vorbehalte ansehen.

2. Unsere Sammlung definieren

Zunächst werden zwei Ansätze veranschaulicht, die die ursprüngliche Datenstruktur mutieren. Dann werden wir über zwei andere Optionen sprechen, die anstelle des Entfernens der Elemente eine Kopie der ursprünglichenCollection ohne diese erstellen.

Verwenden wir die folgende Sammlung in unseren Beispielen, um zu demonstrieren, wie wir mit verschiedenen Methoden dasselbe Ergebnis erzielen können:

Collection names = new ArrayList<>();
names.add("John");
names.add("Ana");
names.add("Mary");
names.add("Anthony");
names.add("Mark");

3. Elemente mitIterator entfernen

MitIterator von Java können wir jedes einzelne Element innerhalb vonCollection gehen und entfernen.

Dazu müssen wir zuerst einen Iterator über seine Elemente mit der Methodeiteratorabrufen. Anschließend können wir jedes Element mit Hilfe vonnext besuchen und mitremove entfernen:

Iterator i = names.iterator();

while(i.hasNext()) {
    String e = i.next();
    if (e.startsWith("A")) {
        i.remove();
    }
}

Trotz seiner Einfachheit gibt es einige Vorbehalte, die wir berücksichtigen sollten:

  • Abhängig von der Sammlung könnenConcurrentModificationExceptionAusnahmen auftreten

  • Wir müssen die Elemente durchlaufen, bevor wir sie entfernen können

  • Depending on the collection, remove may behave differently than expected. E.:ArrayList.Iterator entfernt das Element aus der Sammlung und verschiebt nachfolgende Daten nach links, währendLinkedList.Iterator einfach den Zeiger auf das nächste Element anpasst. Daher istLinkedList.Iterator beim Entfernen von Elementen viel besser alsArrayList.Iterator

4. Java 8 undCollection.removeIf()

Java 8 führte eine neue Methode fürthe Collection interface that provides a more concise way to remove elements using Predicate: ein

names.removeIf(e -> e.startsWith("A"));

Es ist wichtig zu beachten, dassremoveIf im Gegensatz zum Ansatz vonIteratorowohl inLinkedList als auch inArrayList ähnlich gut abschneidet.

In Java 8 überschreibtArrayList die Standardimplementierung - die aufIterator basiert - und implementiert eine andere Strategie: Zunächst werden die Elemente durchlaufen und diejenigen markiert, die mit unserenPredicate; übereinstimmen. Es wird ein zweites Mal wiederholt, um die Elemente zu entfernen (und zu verschieben), die in der ersten Iteration markiert wurden.

5. Java 8 und die Einführung vonStream

Eine der neuen Hauptfunktionen in Java 8 war das Hinzufügen vonStream (undCollectors). Es gibt viele Möglichkeiten, einStream aus einer Quelle zu erstellen. Bei den meisten Vorgängen, die sich auf die Instanz vonStreamauswirken, wird die Quelle jedoch nicht mutiert. Die API konzentriert sich vielmehr darauf, Kopien einer Quelle zu erstellen und alle erforderlichen Vorgänge auszuführen.

Schauen wir uns an, wie wirStream undCollectors verwenden können, um Elemente zu finden / filtern, die mit unserenPredicate übereinstimmen und nicht übereinstimmen.

5.1. Elemente mitStream entfernen

Wenn Siefiltering elements using Stream is quite straightforward entfernen oder besser gesagt, müssen Sie nur eine Instanz vonStream mit unserenCollection erstellen,filter mit unserenPredicate aufrufen und danncollect) s das Ergebnis mit Hilfe vonCollectors:

Collection filteredCollection = names
  .stream()
  .filter(e -> !e.startsWith("A"))
  .collect(Collectors.toList());

Streaming ist weniger invasiv als die vorherigen Ansätze, fördert die Isolation und ermöglicht die Erstellung mehrerer Kopien aus derselben Quelle. Wir sollten jedoch berücksichtigen, dass dadurch auch der von unserer Anwendung verwendete Speicher erhöht wird.

5.2. Collectors.partitioningBy

Das Kombinieren vonStream.filter undCollectors ist sehr praktisch, obwohlwe may run into scenarios where we need both matching and non-matching elements. In solchen Fällen können wirCollectors.partitioningBy nutzen:

Map> classifiedElements = names
    .stream()
    .collect(Collectors.partitioningBy((String e) ->
      !e.startsWith("A")));

String matching = String.join(",",
  classifiedElements.get(true));
String nonMatching = String.join(",",
  classifiedElements.get(false));

Diese Methode gibt einMap zurück, das nur zwei Schlüssel enthält,true undfalse, die jeweils auf eine Liste verweisen, die die übereinstimmenden bzw. nicht übereinstimmenden Elemente enthält.

6. Fazit

In diesem Artikel haben wir uns einige Methoden zum Entfernen von Elementen ausCollections und einige ihrer Einschränkungen angesehen.

Sie finden den vollständigen Quellcode und alle Codefragmente für diesen Artikelover on GitHub.