fundamentals - Java Modcount(ArrayList)
core java volume i--fundamentals, 1(11th edition) pdf (6)
Desde la API de Java para el campo de conteo de mod:
La cantidad de veces que esta lista ha sido modificada estructuralmente. Las modificaciones estructurales son aquellas que cambian el tamaño de la lista o la perturban de tal manera que las iteraciones en progreso pueden arrojar resultados incorrectos.
En Eclipse, veo que los objetos ArrayList
tienen un campo modCount
. ¿Cual es su propósito? (cantidad de modificaciones?)
Es la cantidad de veces que cambia la estructura (tamaño) de la colección
Permite que las partes internas de la lista sepan si se ha realizado una modificación estructural que podría ocasionar que la operación actual arroje resultados incorrectos.
Si alguna vez ha obtenido ConcurrentModificationException
debido a la modificación de una lista (por ejemplo, eliminar un elemento) mientras la itera, su modCount
interno fue lo que modCount
al iterador.
Los documentos AbstractList dan una buena descripción detallada.
Sí. Si alguna vez tiene la intención de extender AbstractList
, debe escribir su código para que adhiera al javadoc de modCount como se menciona a continuación:
/**
* The number of times this list has been <i>structurally modified</i>.
* Structural modifications are those that change the size of the
* list, or otherwise perturb it in such a fashion that iterations in
* progress may yield incorrect results.
*
* <p>This field is used by the iterator and list iterator implementation
* returned by the {@code iterator} and {@code listIterator} methods.
* If the value of this field changes unexpectedly, the iterator (or list
* iterator) will throw a {@code ConcurrentModificationException} in
* response to the {@code next}, {@code remove}, {@code previous},
* {@code set} or {@code add} operations. This provides
* <i>fail-fast</i> behavior, rather than non-deterministic behavior in
* the face of concurrent modification during iteration.
*
* <p><b>Use of this field by subclasses is optional.</b> If a subclass
* wishes to provide fail-fast iterators (and list iterators), then it
* merely has to increment this field in its {@code add(int, E)} and
* {@code remove(int)} methods (and any other methods that it overrides
* that result in structural modifications to the list). A single call to
* {@code add(int, E)} or {@code remove(int)} must add no more than
* one to this field, or the iterators (and list iterators) will throw
* bogus {@code ConcurrentModificationExceptions}. If an implementation
* does not wish to provide fail-fast iterators, this field may be
* ignored.
*/
Echar un vistazo al código fuente real de JDK y leer los javadocs (ya sea en línea o en código) ayuda mucho a entender lo que está sucediendo. Buena suerte.
Yo agregaría que puede agregar código fuente JDK a Eclipse para que cada F3 o CTRL + clic en cualquier clase / método Java SE apunte al código fuente real. Si descarga el JDK, debe tener src.zip en la carpeta de instalación de JDK. Ahora, en el menú superior de Eclipse, vaya a Ventana »Preferencias» Java »JRE instalados. Seleccione el JRE actual y haga clic en Editar. Seleccione el archivo rt.jar, haga clic en Archivos adjuntos de origen, haga clic en Archivo externo, navegue a la carpeta JDK, seleccione el archivo src.zip y añádalo. Ahora el código fuente de la API Java SE está disponible en Eclipse. El código fuente de JDK brinda muchas ideas. Feliz codificación :)
Desde el 1.4 javadoc en AbstractList :
protegido transient int modCount
La cantidad de veces que esta lista ha sido modificada estructuralmente. Las modificaciones estructurales son aquellas que cambian el tamaño de la lista o la perturban de tal manera que las iteraciones en progreso pueden arrojar resultados incorrectos.
Este campo es utilizado por el iterador y la implementación del iterador de lista devuelto por los métodos iterator y listIterator. Si el valor de este campo cambia de forma inesperada, el iterador (o el iterador de la lista) emitirá una ConcurrentModificationException en respuesta a la siguiente, eliminar, establecer, agregar o agregar operaciones. Esto proporciona un comportamiento a prueba de fallos, en lugar de un comportamiento no determinista frente a modificaciones concurrentes durante la iteración.
El uso de este campo por subclases es opcional.
protected transient int modCount = 0;
es la propiedad declarada en public abstract class AbstractList
,
para identificar el número total de modificaciones estructurales hechas en esta colección.
Significa que si hay un add / remove habrá un incremento en este contador para ambas operaciones. Por lo tanto, este contador siempre se incrementa para cualquier modificación. Por lo tanto, no es útil para el cálculo de tamaño.
Esto será útil para lanzar ConcurrentModificationException
.
ConcurrentModificationException
lanzará al iterar la colección por un hilo y hay una modificación en la colección por otro hilo. Esto se logra como cuando se crea un objeto iterador. ModCount se configura en expectedCount, y cada iterador de navegación expectedCount se compara con modCount para lanzar la ConcurrentModificationException
cuando hay un cambio.
private class Itr implements Iterator<E> {
...
...
/**
* The modCount value that the iterator believes that the backing
* List should have. If this expectation is violated, the iterator
* has detected concurrent modification.
*/
int expectedModCount = modCount;
public E next() {
checkForComodification();
...
...
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
...
...
}
size()
api no se adaptará aquí; ya que si hay dos operaciones (agregar y eliminar) pasadas antes del próximo (), el tamaño fijo llamado mostrará el mismo valor; por lo tanto, no es capaz de detectar la modificación ocurrida en esta colección mediante el uso de size()
durante la iteración. Por lo tanto, necesitamos modification_increment_counter que es modCount .