Regola
Utilizzo metodi metodi quando rimuovere dalle collezioni.
Modifica una collezione mentre iterazione su di essa spesso causa errori.
Linguaggi supportati: PY, Java, C/C++, C#,
Swift/Objective-C, Ruby, PHP, Kotlin, Go,
Scala, Rust, Groovy, Dart, Julia, Elixit,
Erlang, Clojure, OCaml, LuaIntroduzione
La rimozione di elementi da una collezione durante l'iterazione provoca eccezioni di modifica concorrente in Java e un comportamento imprevedibile in C#. L'iteratore mantiene un puntatore interno che diventa non valido quando la collezione sottostante subisce modifiche. Ciò comporta il salto di elementi, arresti anomali o cicli infiniti, a seconda del tipo di collezione e dello schema di rimozione utilizzato.
Perché è importante
Stabilità del sistema: le eccezioni dovute a modifiche simultanee causano l'arresto immediato dell'applicazione. In ambiente di produzione, ciò comporta la perdita di richieste e l'indisponibilità del servizio. L'eccezione si verifica spesso in casi limite con dati specifici, rendendo difficile individuarla durante i test.
Integrità dei dati: quando la logica di rimozione fallisce nel corso di un'iterazione, la collezione rimane in uno stato parzialmente modificato. Alcuni elementi vengono rimossi, mentre altri che avrebbero dovuto essere rimossi rimangono. Ciò genera dati incoerenti che influenzano la logica a valle.
Complessità del debug: i bug legati alle modifiche concorrenti dipendono dal tempismo e possono manifestarsi solo con determinate combinazioni di dati. Sono difficili da riprodurre in modo coerente, il che rende complicato il debug e la correzione affidabile.
Esempi di codice
❌ Non conforme:
List<User> users = getUserList();
for (User user : users) {
if (!user.isActive()) {
users.remove(user); // ConcurrentModificationException
}
}
Perché è sbagliato: Rimuovere da utenti mentre l'iterazione con il ciclo "for" potenziato comporta ConcurrentModificationException. L'iteratore rileva che la collezione è stata modificata al di fuori dell'iteratore e genera immediatamente un'eccezione. Gli utenti attivi successivi al primo utente inattivo non vengono mai elaborati.
✅ Conforme:
List<User> users = getUserList();
Iterator<User> iterator = users.iterator();
while (iterator.hasNext()) {
User user = iterator.next();
if (!user.isActive()) {
iterator.remove(); // Safe removal through iterator
}
}
Perché è importante: Utilizzo di iterator.remove() rimuove in modo sicuro gli elementi durante l'iterazione. L'iteratore mantiene uno stato coerente e prosegue l'elaborazione degli elementi rimanenti. Tutti gli utenti inattivi vengono rimossi correttamente senza eccezioni.
Conclusione
Utilizzare gli iteratori remove() metodo per la rimozione sicura durante l'iterazione. In alternativa, utilizzare gli stream con filter() per creare nuove collezioni oppure removeIf() per lo smaltimento di rifiuti ingombranti. Non chiamare mai il servizio di raccolta remove() direttamente durante l'iterazione.

