2009-11-03 3 views
32

Dans Eclipse, je vois que les objets ArrayList ont un champ modCount. Quel est son but? (nombre de modifications?)Java Modcount (ArrayList)

+2

'src.zip' est votre ami. –

+0

voir le code ici http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ListItr – roottraveller

Répondre

28

Il permet aux composants internes de la liste de savoir si une modification structurelle a été effectuée et que l'opération en cours peut entraîner des résultats incorrects.

Si vous avez déjà obtenu ConcurrentModificationException en raison de la modification d'une liste (par exemple, en supprimant un élément) pendant l'itération, son modCount interne était ce qui a incliné l'itérateur. Les AbstractList docs donnent une bonne description détaillée.

+0

Le lien dans votre réponse est cassé, c'est le fixe -https: //docs.oracle.com/javase/7/docs/api/java/util/AbstractList.html#modCount –

+0

Merci pour l'information, mais peut vous développez plus sur les Docs, devinant que les Docs sont toujours incomplets sans un bon exemple. Les docs disent que «les modifications structurelles sont celles qui modifient la taille de la liste, ou la perturbent de telle sorte que les itérations en cours peuvent donner des résultats incorrects», mais que cette perturbation donne-t-elle aux cas? droite. –

15

Oui. Si vous avez l'intention jamais d'étendre AbstractList, vous devez écrire votre code afin qu'il respecte la javadoc du modCount cité ci-dessous:

/** 
* 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. 
*/ 

Prendre un coup d'oeil dans le code source JDK réelle et la lecture des javadocs (en ligne ou en code) aide beaucoup à comprendre ce qui se passe. Bonne chance. J'ajouterais que vous pouvez ajouter du code source JDK à Eclipse afin que chaque F3 ou CTRL + clic sur n'importe quelle classe/méthode Java SE pointe sur le code source réel. Si vous téléchargez le JDK, vous devriez avoir le src.zip dans le dossier d'installation du JDK. Maintenant, dans le menu principal d'Eclipse, allez dans Fenêtre »Préférences» Java »JRE installés. Sélectionnez le JRE actuel et cliquez sur Modifier. Sélectionnez le fichier rt.jar, cliquez sur Pièce jointe, cliquez sur Fichier externe, naviguez vers le dossier JDK, sélectionnez le fichier src.zip et ajoutez-le. Maintenant, le code source de l'API Java SE est disponible dans Eclipse. Le code source JDK donne un lot des aperçus. Bonne programmation :)

+1

J'ai ajouté quelques explications comment intégrer le code source Java SE dans Eclipse. La question originale m'a fait penser qu'il ne l'avait pas déjà fait alors que c'est un MUST pour tous les développeurs Java. – BalusC

1

De l'Java API pour le champ de comptage mod:

Le nombre de fois cette liste a été modifiée dans sa structure. Les modifications structurelles sont celles qui modifient la taille de la liste ou la perturbent de telle sorte que les itérations en cours peuvent donner des résultats incorrects.

4

Il est le nombre de fois la structure (taille) de la collection change

0

From the 1.4 javadoc on AbstractList:

int transitoire protégé modCount

Le nombre de fois cette liste a été structurellement modifié. Les modifications structurelles sont celles qui changent la taille de la liste, ou sinon le perturbent de telle manière que itérations en cours peut donner des résultats incorrects .

Ce champ est utilisé par l'itérateur et liste mise en œuvre de iterator retourné par le iterator et les méthodes ListIterator . Si la valeur de ce champ change de façon inattendue, l'itérateur (ou l'itérateur de liste ) affichera ConcurrentModificationException dans en réponse à la suivante, supprimer, précédemment, définir ou ajouter des opérations. Ce fournit un comportement rapide, plutôt qu'un comportement non-déterministe dans la face de la modification simultanée au cours de l'itération .

L'utilisation de ce champ par sous-classes est facultative.

2

protected transient int modCount = 0;
est la propriété déclarée à public abstract class AbstractList,
pour identifier le nombre total de modification structurelle faite dans cette collection.

Signifie que s'il y a un ajout/retrait, il y aura un incrément dans ce compteur pour les deux opérations. Par conséquent, ce compteur est toujours incrémenté pour toute modification. Donc pas utile pour le calcul de la taille. Il sera utile de lancer ConcurrentModificationException.
ConcurrentModificationException sera levée lors de l'itération de la collection par un thread et il y a une modification dans la collection par un autre thread. Ceci est réalisé comme chaque fois que l'objet itérateur est créé, modCount sera défini dans expectedCount, et chaque itérateur expectedCount sera comparé avec modCount pour lancer ConcurrentModificationException lorsqu'il y a une modification.

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 ne convient pas ici; car s'il y a deux opérations (ajouter et supprimer) qui se sont passées avant que next() appelle la taille fixe affichera la même valeur; donc pas en mesure de détecter la modification est arrivé sur cette collection en utilisant size() api lors de l'itération. Nous avons donc besoin de modification_increment_counter qui estmodCount.

+0

superbe. voir le code complet ici: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ListItr – roottraveller