Suppression d’éléments de collections Java

Supprimer des éléments de collections Java

1. Vue d'ensemble

Dans ce tutoriel rapide,we’re going to talk about four different ways to remove items from Java Collections that match certain predicates.

Nous examinerons naturellement également certaines des mises en garde.

2. Définir notre collection

Tout d'abord, nous allons illustrer deux approches qui modifient la structure de données d'origine. Ensuite, nous parlerons de deux autres options qui, au lieu de supprimer les éléments, créeront une copie desCollectionoriginaux sans eux.

Utilisons la collection suivante tout au long de nos exemples pour montrer comment nous pouvons obtenir le même résultat en utilisant différentes méthodes:

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

3. Suppression d'éléments avecIterator

LesIterator de Java nous permettent à la fois de parcourir et de supprimer chaque élément individuel dans unCollection.

Pour ce faire, nous devons d'abord récupérer un itérateur sur ses éléments en utilisant la méthodeiterator. Ensuite, nous pouvons visiter chaque élément à l'aide denext et les supprimer en utilisantremove:

Iterator i = names.iterator();

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

Malgré sa simplicité, il convient de tenir compte de certaines réserves:

  • Selon la collection, nous pouvons rencontrer des exceptionsConcurrentModificationException

  • Nous devons parcourir les éléments avant de pouvoir les supprimer

  • Depending on the collection, remove may behave differently than expected.  Par exemple:ArrayList.Iterator supprime l'élément de la collection et décale les données suivantes vers la gauche tandis queLinkedList.Iterator ajuste simplement le pointeur vers l'élément suivant. En tant que tel,LinkedList.Iterator fonctionne bien mieux queArrayList.Iterator lors de la suppression d'éléments

4. Java 8 etCollection.removeIf()

Java 8 a introduit une nouvelle méthode pourthe Collection interface that provides a more concise way to remove elements using Predicate:

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

Il est important de noter que contrairement à l’approcheIterator,removeIf fonctionne de manière similaire dansLinkedList etArrayList.

Dans Java 8,ArrayList remplace l'implémentation par défaut - qui repose surIterator - et implémente une stratégie différente: d'abord, il itère sur les éléments et marque ensuite ceux qui correspondent à nosPredicate;, il répète une seconde fois pour supprimer (et décaler) les éléments marqués lors de la première itération.

5. Java 8 et l'introduction deStream

L'une des nouvelles fonctionnalités majeures de Java 8 était l'ajout deStream (etCollectors). Il existe de nombreuses façons de créer unStream à partir d'une source. Cependant, la plupart des opérations qui affectent l'instanceStream ne muteront pas sa source, mais plutôt, l'API se concentre sur la création de copies d'une source et l'exécution de toute opération dont nous pourrions avoir besoin.

Voyons comment nous pouvons utiliserStream etCollectors pour trouver / filtrer les éléments qui correspondent, et ne correspondent pas, à nosPredicate.

5.1. Suppression d'éléments avecStream

En supprimant, ou plutôt,filtering elements using Stream is quite straightforward, nous devons juste créer une instance deStream en utilisant nosCollection, invoquerfilter avec nosPredicate puiscollect) s le résultat à l'aide deCollectors:

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

Streaming est moins invasif que les approches précédentes, il favorise l'isolement et permet la création de plusieurs copies à partir de la même source. Cependant, nous devons garder à l'esprit que cela augmente également la mémoire utilisée par notre application.

5.2. Collectors.partitioningBy

Combiner à la foisStream.filter etCollectors est assez pratique, bien quewe may run into scenarios where we need both matching and non-matching elements. Dans de tels cas, nous pouvons profiter deCollectors.partitioningBy:

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));

Cette méthode renvoie unMap qui ne contient que deux clés,true etfalse, chacune pointant vers une liste contenant respectivement les éléments correspondants et non correspondants.

6. Conclusion

Dans cet article, nous avons examiné certaines méthodes pour supprimer des éléments deCollections et certaines de leurs mises en garde.

Vous pouvez trouver le code source complet et tous les extraits de code pour cet articleover on GitHub.