331 votes

Supprimer des éléments de la collection tout en itérant

De ce que je sache, il existe deux approches :

  1. Parcourir une copie de la collection
  2. Utiliser l'itérateur de la collection réelle

Par exemple,

List fooListCopy = new ArrayList(fooList);
for(Foo foo : fooListCopy){
    // modifier la liste fooList actuelle
}

et

Iterator itr = fooList.iterator();
while(itr.hasNext()){
    // modifier la liste fooList actuelle en utilisant itr.remove()
}

Y a-t-il des raisons de préférer une approche à l'autre (par exemple, préférer la première approche pour la simple raison de lisibilité) ?

1voto

Jon Points 1381

Vous ne pouvez pas faire le deuxième, car même si vous utilisez la méthode remove() sur Iterator, vous obtiendrez une Exception lancée.

Personnellement, je préfère le premier pour toutes les instances de Collection, malgré le surcoût additionnel de la création de la nouvelle Collection, je trouve qu'elle est moins sujette aux erreurs lors de la modification par d'autres développeurs. Sur certaines implémentations de Collection, la méthode remove() de l'Iterator est supportée, sur d'autres non. Vous pouvez en lire plus dans la documentation pour Iterator.

La troisième alternative est de créer une nouvelle Collection, itérer sur l'originale, et ajouter tous les membres de la première Collection à la deuxième Collection qui ne sont pas destinés à être supprimés. En fonction de la taille de la Collection et du nombre de suppressions, cela pourrait économiser significativement de la mémoire, comparé à la première approche.

0voto

Calin Andrei Points 166

Je choisirais le deuxième car vous n'avez pas à faire de copie de la mémoire et l'itérateur fonctionne plus rapidement. Ainsi, vous économisez de la mémoire et du temps.

0voto

Golam Kibria Points 1

Vous pouvez voir cet exemple; Si nous pensons supprimer les valeurs impaires d'une liste:

public static void main(String[] args) {
    Predicate isOdd = v -> v % 2 == 0;
    List listArr = Arrays.asList(5, 7, 90, 11, 55, 60);
    listArr = listArr.stream().filter(isOdd).collect(Collectors.toList());
    listArr.forEach(System.out::println);
}

-6voto

Drake Clarris Points 1053

Pourquoi pas ceci?

for( int i = 0; i < Foo.size(); i++ )
{
   if( Foo.get(i).equals( some test ) )
   {
      Foo.remove(i);
   }
}

Et si c'est une map, et non une liste, vous pouvez utiliser keyset()

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X