Regla
Uso métodos métodos cuando eliminar de colecciones.
Modificar una colección mientras iterar sobre ella a menudo provoca errores.
Idiomas compatibles: PY, Java, C/C++, C#,
Swift/Objective-C, Ruby, PHP, Kotlin, Go,
Scala, Rust, Groovy, Dart, Julia, Elixit,
Erlang, Clojure, OCaml, LuaIntroducción
Eliminar elementos de una colección durante la iteración causa excepciones de modificación concurrente en Java y un comportamiento impredecible en C#. El iterador mantiene un puntero interno que se invalida cuando la colección subyacente cambia. Esto lleva a elementos omitidos, fallos o bucles infinitos, dependiendo del tipo de colección y el patrón de eliminación utilizado.
Por qué es importante
Estabilidad del sistema: Las excepciones de modificación concurrente bloquean la aplicación inmediatamente. En producción, esto significa solicitudes perdidas e indisponibilidad del servicio. La excepción a menudo ocurre en casos límite con datos específicos, lo que dificulta su detección durante las pruebas.
Integridad de los datos: Cuando la lógica de eliminación falla a mitad de una iteración, la colección queda en un estado parcialmente modificado. Algunos elementos se eliminan, mientras que otros que deberían haberse eliminado permanecen. Esto crea datos inconsistentes que afectan la lógica posterior.
Complejidad de la depuración: Los errores de modificación concurrente dependen del tiempo y solo pueden manifestarse con ciertas combinaciones de datos. Son difíciles de reproducir de forma consistente, lo que los hace difíciles de depurar y corregir de manera fiable.
Ejemplos de código
❌ No conforme:
List<User> users = getUserList();
for (User user : users) {
if (!user.isActive()) {
users.remove(user); // ConcurrentModificationException
}
}
Por qué es incorrecto: Eliminando de usuarios mientras que la iteración con un bucle for mejorado causa ConcurrentModificationException. El iterador detecta que la colección fue modificada fuera del iterador y lanza una excepción inmediatamente. Cualquier usuario activo después del primero inactivo nunca es procesado.
✅ 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
}
}
¿Por qué esto importa? Uso iterator.remove() elimina elementos de forma segura durante la iteración. El iterador mantiene un estado consistente y continúa procesando los elementos restantes. Todos los usuarios inactivos se eliminan correctamente sin excepciones.
Conclusión
Utilice iteradores remove() método para una eliminación segura durante la iteración. Alternativamente, utilice streams con filter() para crear nuevas colecciones o removeIf() para eliminación masiva. Nunca llame a la colección de remove() directamente mientras se itera.
.avif)
