J'ai déjà lu une phrase, et c'était très bien. Quelqu'un a demandé quel est l'utilisation du code source de lecture? Apprenez les idées de conception des autres pour mettre en œuvre une certaine fonction et améliorer votre niveau de programmation.
Oui, tout le monde implémente une fonction. Différentes personnes ont des idées de conception différentes. Certaines personnes utilisent 10 000 lignes de code et certaines personnes utilisent 5 000 lignes. Certaines personnes doivent exécuter le code pendant des dizaines de secondes, tandis que d'autres n'ont besoin que de quelques secondes. . Passons au sujet ci-dessous.
Contenu principal de cet article:
・Un commentaire détaillé sur l'implémentation de ArrayList, basé sur JDK 1.8.
・La partie subliste de l'itérateur n'a pas été expliquée en détail et sera placée dans d'autres interprétations de code source. Nous nous concentrons ici sur la mise en œuvre de ArrayList lui-même.
・Aucune annotation standard n'est utilisée, et l'indentation du code est ajustée de manière appropriée pour une introduction facile
Importer java.util.abstractList; import java.util.arrays; import java.util.bitset; import java.util.collection; import java.util.comparator; import java.util.concurrentmodificationException; import java.util.iterator; import java.util.list; import java.util.Lesterator; import; java.util.nosuchementElementException; import java.util.objects; importer java.util.randomaccess; import java.util.spliterator; import java.util.function.consumer; import java.util.function.predicate; importer java.util.function.overator; / ** operview: impleweation de l'arrayation de la finition de la finition; L'interface de liste qui peut être redimensionnée. Implémentez toutes les opérations de liste facultative et permettez à tous les éléments, y compris null, d'être reproductibles. * En plus de l'interface de liste, cette classe fournit un moyen de manipuler la taille du tableau pour stocker la taille du tableau dans la liste. * * Complexité du temps: * Les appels à la taille des méthodes, iSempty, get, set, iterator et listIterator sont un temps constant. * La complexité temporelle de l'ajout et de la suppression est O (n). Toutes les autres opérations sont la complexité du temps linéaire. * * Capacité: * Chaque arraylist a une capacité, et la taille de la capacité est au moins la longueur de l'élément de liste, et l'initialisation par défaut est 10. * La capacité peut être automatiquement augmentée. * Si vous savez à l'avance qu'il existe de nombreux éléments dans le tableau, vous pouvez augmenter la capacité à l'avance en appelant la méthode Assurecapacity () avant d'ajouter des éléments pour réduire les frais généraux de la croissance automatique de la capacité dans la période ultérieure. * Cette capacité peut également être initialisée par un constructeur avec une capacité initiale. * * Le thread n'est pas sûr: * ArrayList n'est pas sûr de fil. * S'il doit être appliqué à Multithreads, la synchronisation doit être effectuée en externe * * modCount: * définie dans AbstractList: TRANSIGNAGE INT MODCOUPT = 0; * Nombre de fois cette liste a été modifiée structurellement. La modification structurelle fait référence à la modification de la taille de la liste ou à la perturbation de la liste, de sorte que l'itération en cours produit des résultats incorrects. * Ce champ est utilisé par les implémentations Iterator et List Iterator renvoyées par les méthodes d'itérateur et de lister. * Si la valeur de ce champ est accidentellement modifiée, l'itérateur (ou list itérateur) lancera une conception en concurrentModification en réponse à des opérations suivantes, supprimées, précédentes, définies ou ajouter. * Face à des modifications simultanées pendant les itérations, il fournit un comportement défaillant rapide plutôt qu'un comportement non déterministe. * Si la sous-classe utilise ce champ est facultatif. * Si la sous-classe souhaite fournir un itérateur de défaillance rapide (et lister iterator), il ajoute simplement ce champ à ses méthodes ADD (int, e) et supprimez (int) (et toute autre méthode qu'il remplace, entraînant des modifications sur la structure de la liste). * Le nombre d'appels uniques à ajouter (int, e) ou supprimer (int) ne doit pas dépasser 1 dans ce champ, sinon l'ITERATOR (et LIST ITERATOR) lancera de faussesceptions de modification concurrent. * Si une implémentation ne veut pas fournir un itérateur de défaillance rapide, ce champ peut être ignoré. * * Transient: * Par défaut, toutes les variables membre d'un objet seront persistées. Dans certains cas, si vous souhaitez éviter de persister certaines variables de membres d'un objet, vous pouvez utiliser le mot-clé transitoire pour les taguer, qui est également un mot réservé dans Java (JDK 1.8) * / classe publique ArrayList <e> étend AbstractList <e> implémente List <e>, RandomAccess, Clonable, Java.io.Serializable {private static final SERALSIONUID = Java.Serializable {private Static Final SerialSioniid = Java.Serializable {private static Final SERALIONIDIONUID = JAVA. 8683452581122892189L; // Capacité initiale par défaut Private Static Final int default_capacity = 10; // Utilisé pour partager des instances de tableau vides avec des instances vides. objet final statique privé [] vide_elementData = {}; // par défaut Vide Array Private Static Final Object [] DefaultCapacity_Empty_elementData = {}; // Pour la droite, le tableau d'éléments, les autorisations d'accès aux packages sont des objets transitoires stockés [] elementData; // taille, Java initialisera INT à 0 lors de la création d'un objet privé INT size; // Définissez le constructeur de la capacité d'initialisation avec le nombre spécifié, et le nombre négatif lancera une exception publique ArrayList (int initialCapacity) {if (initialCapacity> 0) {this.elementData = new objet [initialCapacity]; } else if (initialCapacity == 0) {this.elementData = vide_elementData; } else {lance un nouveau IllégalArgumentException ("Capacité illégale:" + InitialCapacity); }} // Constructeur par défaut, utilisez le tableau de contrôle pour initialiser publique ArrayList () {this.elementData = defaultCapacity_empty_elementData; } // Construisez une liste contenant des éléments dans la collection dans l'ordre du retour itérateur de la collection publique ArrayList (Collection <? Étend e> c) {elementData = c.toArray (); if ((size = elementData.Length)! = 0) {// C.ToArray peut (erreur) non return objet [] (voir le numéro de bug java 6260652) if (elementData.getClass ()! = objet []. class) elementData = arrays.copyof (elementData, size, objet []. class); } else {// Utilisez un tableau vide this.elementData = vide_elementData; }} // Parce que la capacité est souvent supérieure au nombre réel d'éléments. Lorsque la mémoire est serrée, vous pouvez appeler cette méthode pour supprimer l'emplacement réservé et ajuster la capacité au nombre réel d'éléments. // Si vous êtes sûr qu'aucun éléments ne sera ajouté, vous pouvez également appeler cette méthode pour enregistrer l'espace public void trimToSize () {modCount ++; if (size <elementData.length) {elementData = (size == 0)? Vide_elementData: arrays.copyof (elementData, taille); }} // Définissez la capacité du tableau avec des paramètres spécifiés publics void assurecapacity (int mincapacity) {// Si le tableau est vide, préfèret 0, sinon, allez à la valeur par défaut (10) int minexpand = (elementData! = DefaultCapacity_Empty_elementData)? 0: default_capacity; // Si le paramètre est supérieur à la capacité prédéfinie, utilisez ce paramètre pour définir davantage la capacité du tableau if (mincapacity> mineXpand) {assurexplicitCapacity (mincapacity); }} // Lors de l'ajout d'éléments, assurez-vous que la capacité du tableau private void assurecapacityInternal (int mincapacity) {// utilise la valeur par défaut et le paramètre plus grand comme valeur préréglante de capacité if (elementData == defaultcapacity_empty_elementData) {mincapacity = math.max (default_capactity, mincapacity); } assure lacapacité (mincapacité); } // Si le paramètre est supérieur à la capacité du tableau, augmentez la capacité du tableau privé void assurexplicitCapacity (int mincapacity) {modCount ++; if (mincapacity - elementData.length> 0) se développer (mincapacité); } // La capacité maximale du tableau peut provoquer un débordement de mémoire (limite de mémoire VM) final statique privé int max_array_size = Integer.max_value - 8; // augmente la capacité de s'assurer qu'il peut contenir au moins le nombre d'éléments spécifiés par le paramètre privé void Grow (int mincapacity) {int oldcapacity = elementData.length; // Augmentez la capacité prédéfinie de la moitié int newcapacity = oldcapacity + (oldcapacity >> 1); // prenez la valeur plus grande du paramètre if (newCapacity - mincapacity <0) // c'est-à-dire, newcapacity <mincapacity newcapacity = mincapacity; // Si la valeur prédéfinie est supérieure au maximum par défaut, vérifiez s'il déborde si (newCapacity - max_array_size> 0) newCapacity = HugeCapacity (Mincapacity); elementData = arrays.copyof (elementData, newCapacity); } // Vérifiez s'il déborde. S'il n'y a pas de débordement, renvoyez la valeur entière maximale (l'int en java est de 4 octets, donc le maximum est 0x7ffffffff) ou la valeur maximale par défaut private static int HugeCapacity (int mincapacity) {if (mincapacity <0) // débordera de nouveaux OutofMemoryError (); return (mincapacity> max_array_size)? Integer.max_value: max_array_size; } // retourne la taille du tableau public int size () {return size; } // Est-ce que le public est vide booléen iSempty () {return size == 0; } // Qu'il contient un nombre, RETOUR BOOL PUBLIC BOOLEAN contient (objet o) {return indexof (o)> = 0; } // Renvoie une valeur à la première apparition du tableau, et elle sera jugée de différentes manières selon qu'elle est nul. S'il n'existe pas, il renvoie -1. La complexité temporelle est o (n) public int indexof (objet o) {if (o == null) {for (int i = 0; i <size; i ++) if (elementData [i] == null) return i; } else {for (int i = 0; i <size; i ++) if (o.equals (elementData [i])) return i; } return -1; } // Renvoie une valeur à la dernière fois lorsqu'il apparaît dans le tableau. S'il n'existe pas, il renvoie -1. La complexité temporelle est o (n) public int lastIndexof (objet o) {if (o == null) {for (int i = size-1; i> = 0; i--) if (elementData [i] == null) return i; } else {for (int i = size-1; i> = 0; i--) if (o.equals (elementData [i])) return i; } return -1; } // Renvoie la copie, l'élément lui-même n'a pas été copié et une exception sera lancée lorsque le tableau du processus de copie change clone d'objet public () {try {ArrayList <?> V = (ArrayList <?>) Super.clone (); v.ElementData = arrays.copyof (elementData, taille); v.modCount = 0; retour v; } catch (clonenotsupportedException e) {lancer un nouveau interneurror (e); }} // Convertir en un tableau d'objets, utilisez les arrays.copyof () Méthode Objet public [] toArray () {return arrays.copyof (elementData, size); } // Renvoie un tableau, utilisez le temps d'exécution pour déterminer le type, et le tableau contient tous les éléments de cette liste (du premier au dernier élément) // La capacité de tableau renvoyée est déterminée par les paramètres et la plus grande valeur dans ce tableau @suppresswarning Arrays.Copyof (elementData, Size, A.getClass ()); System.ArrayCopy (ElementData, 0, A, 0, taille); if (a.length> taille) a [size] = null; retourner a; } // Renvoie la valeur de la position spécifiée, car il s'agit d'un tableau, il est particulièrement rapide @SuppressWarnings ("Unchecked") e elementData (int index) {return (e) elementData [index]; } // Renvoie la valeur de la position spécifiée, mais vérifiez si le nombre de positions dépasse la longueur du tableau public e get (int index) {RangECheck (index); return elementData (index); } // Définissez la position spécifiée sur une nouvelle valeur et renvoyez la valeur précédente, vérifiez si cette position dépasse la longueur du tableau publique E Set (int index, e élément) {rangeCheck (index); E oldValue = elementData (index); elementData [index] = élément; Retour OldValue; } // Ajouter une valeur assure d'abord la capacité publique booléen add (e e) {assurecapacityInternal (taille + 1); elementData [size ++] = e; Retour Vrai; } // Ajouter une valeur dans la position spécifiée et vérifier la position et la capacité publiques void add (int index, e élément) {rangeCheckForAdd (index); AssurecapacityInternal (taille + 1); // public static void arrayCopy (objet src, int srcpos, objet dest, int destpos, int le long) // src: array source; SRCPOS: La position de départ du tableau source à copier; DEST: Array de destination; destpos: la position de départ du tableau de destination; Longueur: Copy Length System.ArrayCopy (élémentData, index, elementData, index + 1, taille - index); elementData [index] = élément; taille ++; } // Supprimez la valeur de la position spécifiée, vérifiez la position ajoutée et renvoyez la valeur précédente publique retiraiment (int index) {rangeCheck (index); modCount ++; E oldValue = elementData (index); int numMoved = size - index - 1; if (numMoved> 0) System.ArrayCopy (elementData, index + 1, elementData, index, numMoved); elementData [- size] = null; // Facile à recycler la période de collecte des ordures Retour OldValue; } // Supprimer l'emplacement où l'élément spécifié apparaît d'abord public booléen supprime (objet o) {if (o == null) {for (int index = 0; index <size; index ++) if (elementData [index] == null) {fastRemove (index); Retour Vrai; }} else {for (int index = 0; index <size; index ++) if (o.equals (elementData [index])) {fastRemove (index); Retour Vrai; }} return false; } // Supprimez rapidement la valeur à la position spécifiée. La raison pour laquelle on l'appelle Fast devrait être qu'il n'est pas nécessaire de vérifier et de renvoyer la valeur, car seul le void privé FastRemove (int index) {modCount ++; int numMoved = size - index - 1; if (numMoved> 0) System.ArrayCopy (elementData, index + 1, elementData, index, numMoved); elementData [- size] = null; // Clear pour permettre à GC d'effectuer son travail} // efface le tableau et définissez chaque valeur sur NULL pour faciliter la collecte des ordures (contrairement à la réinitialisation, la taille par défaut du tableau ne sera pas réinitialisée si elle change) public void clear () {modCount ++; pour (int i = 0; i <size; i ++) elementData [i] = null; taille = 0; } // Ajouter un élément d'une collection à la fin, si la collection à ajouter est vide, renvoyez False Boolean Addall public (collection <? Étend e> c) {objet [] a = c.toarray (); int numNew = a.Length; AssurecapacityInternal (taille + numnew); System.ArrayCopy (A, 0, ElementData, Size, Numnew); taille + = numnew; retourner numnew! = 0; } // La fonction est la même que ci-dessus, Ajouter le booléen public addall (int index, collection <? Étend e> c) {rangeCheckForAdd (index); Objet [] a = c.toArray (); // Le tableau à ajouter int numNew = a.Length; // La longueur du tableau à ajouter s'assureraCapacityInternal (taille + numnew); // Assurer la capacité int numMoved = size - index; // la longueur qui ne bougera pas (la partie précédente) if (numMoved> 0) // s'il n'est pas nécessaire de se déplacer, de le copier seul et de déplacer la partie arrière du tableau vers le système de position correct.ArrayCopy (élémentData, index, elementData, index + numnew, numMoved); System.ArrayCopy (A, 0, ElementData, Index, NumNew); // Ajouter un nouveau tableau au milieu de la taille du tableau d'origine modifiée + = numnew; retourner numnew! = 0; } // Supprimer l'élément de plage spécifié. Les paramètres sont les positions de démarrage et de terminaison protégés vides de Removerange (int fromIndex, int toindex) {modCount ++; int numMoved = size - toindex; // la longueur conservée par cette dernière section System.ArrayCopy (ElementData, Toindex, ElementData, FromIndex, NumMoved); int NewSize = size - (toindex-fromidex); for (int i = newsize; i <size; i ++) {elementData [i] = null; } size = NewSize; } // Vérifiez si le nombre dépasse la longueur du tableau lors de l'ajout d'éléments private void RangECHeck (int index) {if (index> = size) lancez un nouvel indexoutofboundSException (uutofboundsmsg (index)); } // Vérifiez si private void RangECHECKForAdd (int index) {if (index> size || index <0) lancez un nouvel indexoutofboundSexception (uutofboundsmsg (index)); } // Détails de l'exception lancée Private String OutOfBoundSmsg (int index)) {return "index:" + index + ", taille:" + size; } // Supprimer l'élément de la collection spécifiée publique booléen remonteall (collection <?> C) {objets.requireNonnull (c); // Vérifiez si le paramètre est null return batchRemove (c, false); } // conserver uniquement les éléments de la collection spécifiée publique Boolean Retainall (Collection <?> C) {objets.RequiRenonnull (C); retour BatchRemove (C, true); } / ** * Interprétation du code source par http://anxpp.com/ * @param complet Lorsque vous êtes vrai, la valeur de l'élément de la collection spécifiée est conservée du tableau, et lorsqu'il est faux, la valeur de l'élément dans la collection spécifiée est supprimée du tableau. * @return Les éléments en double dans le tableau seront supprimés (plutôt que simplement supprimés une ou plusieurs fois), et toute opération de suppression renverra True * / BatchRemRemove booléen privé (Collection <?> C, complément booléen) {objet final [] elementData = this.elementData; int r = 0, w = 0; booléen modifié = false; Essayez {// Transweep via le tableau et vérifiez si cette collection contient la valeur correspondante, déplacez la valeur à conserver vers l'avant du tableau, et la dernière valeur de W est le nombre d'éléments à conserver // point simple: si vous retenez, déplacez le même élément vers la section précédente; En cas de suppression, déplacez différents éléments vers la section précédente pour (; r <size; r ++) if (c.Contains (elementData [r]) == complément) elementData [w ++] = elementData [r]; } Enfin {// Assurez-vous que la pièce avant l'exception est lancée peut terminer l'opération attendue, tandis que la pièce qui n'a pas été traversée sera connectée à l'arrière // r! = La taille signifie qu'une erreur peut se produire: C.CONTAINS (élémentData [R]) lance une exception si (r! = size) {System.arrayCopy (élémentData, r, elementData, w, size-r); w + = taille - r; } // Si w == Taille: signifie que tous les éléments sont conservés, donc aucune opération de suppression ne se produit, donc FALSE sera retourné; Sinon, vrai et le tableau // lorsque W! = La taille est renvoyée, même si le bloc d'essai lance une exception, l'opération avant l'exception est lancée, car W est toujours la longueur de la partie précédente à conserver, et le tableau ne sera pas hors service parce que (w! = taille) {pour (int i = w; i <size; i ++) elementData [i] = null; modCount + = size - w; // Le nombre de fois de taille modifiée = w; // La nouvelle taille est le nombre d'éléments conservés modifiés = true; }} return modifié; } // Enregistrez l'état de l'instance de tableau sur un flux (c'est-à-dire qu'il est sérialisé). Le tableau de processus d'écriture est modifié et une exception sera lancée private void writeObject (java.io.objectOutputStream s) lève java.io.ioException {int attendModCount = modCount; S.DefaultWriteObject (); // Exécuter le processus de désérialisation / sérialisation par défaut. Écrivez des champs non statiques et non transitoires de la classe actuelle à ce flux // Écrivez à S.WriteInt (taille); // Écrivez tous les éléments dans l'ordre (int i = 0; i <size; i ++) {s.writeObject (elementData [i]); } if (modCount! = attendModCount) {Throw New ConcurrentModificationException (); }} // Ce qui précède est écrit, ceci est lu. private void readObject (java.io.objectInputStream s) lève java.io.ioException, classNotFoundException {elementData = vide_elementData; // Effectuez le processus de sérialisation / désérialisation par défaut S.DefaulTreadObject (); // Lire dans la longueur du tableau S.ReadInt (); if (size> 0) {assurecapacityInternal (taille); Objet [] a = elementData; // Lire dans tous les éléments pour (int i = 0; i <size; i ++) {a [i] = s.ReadObject (); }}}} // return listIterator, la position de départ est le paramètre spécifié public listIterator <e> listIterator (int index) {if (index <0 || index> size) lancez la nouvelle indexoutofboundSException ("index:" + index); return new listRitr (index); } // return listIterator, la position de départ est 0 public listIterator <e> lisTiterator () {return new listRitr (0); } // Renvoie un itérateur ordinaire ordinaire iterator <e> iterator () {return new itr (); } // L'Iterator général implémente la classe privée ITR implémente Iterator <e> {int Cursor; // Le curseur, l'index de l'élément suivant, l'initialisation par défaut est 0 int lastret = -1; // La position du dernier élément consulté est int } // L'élément suivant @SuppressWarnings ("Unchecked") public e suivant () {checkForComodification (); // Vérifiez si le tableau est modifié int i = curseur; if (i> = size) lancez new nosuchementElementException (); Object [] elementData = arrayList.this.ElementData; if (i> = elementData.Length) lancez de nouveaux mododification ConcurrentException (); curseur = i + 1; // déplace le curseur en arrière retour (e) elementData [lastret = i]; // Définissez la position d'accès et renvoyez cette valeur} // Supprimer l'élément public void remove () {if (lastret <0) lancez new illégalStateException (); CheckForComodification (); // Vérifiez si le tableau est modifié TRY {ArrayList.This.Remove (lastret); Cursor = lastret; lastret = -1; attendModCount = modCount; } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }} @Override @SuppressWarnings ("Unchecked") public void ForEachRemaining (Consumer <? Super E> Consumer) {objets.RequiRenonnull (consommateur); Final int size = arrayList.this.size; int i = curseur; if (i> = size) {return; } objet final [] elementData = arrayList.this.ElementData; if (i> = elementData.length) {lancez new concurrentModificationException (); } while (i! = size && modCount == attendModCount) {Consumer.Accept ((e) elementData [i ++]); } curseur = i; lastret = i - 1; checkForComodification (); } // Vérifiez si le tableau est modifié final void checkForComodification () {if (modCount! = AttendModCount) New concurrentModificationException (); }} // listIterator iterator implémente la classe privée listitr étend ITR implémente ListIterator <e> {listItrTr (int index) {super (); curseur = index; } public boolean hasprevious () {return Cursor! = 0; } public int nextIndex () {return Cursor; } public int promedIndex () {return Cursor - 1; } @SuppressWarnings ("Unchecked") public e précédemment () {checkForComodification (); int i = curseur - 1; if (i <0) lancer un nouveau nosuchementElementException (); Object [] elementData = arrayList.this.ElementData; if (i> = elementData.Length) lancez de nouveaux mododification ConcurrentException (); curseur = i; return (e) elementData [lastret = i]; } public void set (e e) {if (lastret <0) lance un nouveau illégalStateException (); checkForComodification (); essayez {arrayList.this.set (lastret, e); } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }} public void add (e e) {checkForComodification (); essayez {int i = curseur; ArrayList.This.add (i, e); curseur = i + 1; lastret = -1; attendModCount = modCount; } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }}} // Renvoie le sous-réseau de la liste publique de la plage spécifiée <e> sublist (int FromIndex, int toindex) {sublistrangeCheck (FromIndex, toindex, size); retourner un nouveau subliste (ce, 0, FromIndex, toindex); } // Sécurité Check static void sublistrangeCheck (int fromIndex, int to Toindex, int size) {if (FromIndex <0) lance un nouvel indexoutofboundSexception ("FromIndex =" + FromIndex); if (toindex> taille) lancez un nouvel indexoutofboundSexception ("toindex =" + toindex); if (fromIndex> toindex) lancez un nouveau IllégalArgumentException ("FromIndex (" + FromIndex + ")> ToIndex (" + ToIndex + ")"); } // sous-réseau La classe privée Sublist étend AbstractList <e> implémente RandomAccess {private final abstractList <e> parent; private final int parentoffset; Offset INT final privé; Taille int; Sublist (abstractList <e> parent, int offset, int fromIndex, int to Toindex) {this.parent = parent; this.parentoffset = fromIndex; this.offset = offset + fromIndex; this.size = toindex - fromIndex; this.modCount = arrayList.this.modCount; } public e set (int index, e e) {rangeCheck (index); checkForComodification (); E oldvalue = arrayList.this.elementData (offset + index); ArrayList.this.ElementData [Offset + index] = e; Retour OldValue; } public e get (int index) {rangeCheck (index); checkForComodification (); return arrayList.this.elementData (Offset + index); } public int size () {checkForComodification (); Renvoyez ceci.Size; } public void add (int index, e e) {rangeCheckForAdd (index); checkForComodification (); parent.add (parentoffset + index, e); this.modCount = parent.modCount; this.size ++; } public e repos (int index) {rangeCheck (index); checkForComodification (); E result = Parent.Remove (parentoffset + index); this.modCount = parent.modCount; this.size--; Résultat de retour; } Protected void Removerange (int fromIndex, int toindex) {checkForComodification (); Parent.Removerange (parentoffset + fromIndex, parentoffset + toindex); this.modCount = parent.modCount; this.size - = toindex - fromIndex; } public boolean addall (collection <? étend e> c) {return addall (this.size, c); } public boolean addall (int index, collection <? étend e> c) {rangeCheckForAdd (index); int cSize = c.size (); if (cSize == 0) return false; checkForComodification (); parent.addall (parentoffset + index, c); this.modCount = parent.modCount; this.size + = cSize; Retour Vrai; } public iterator <e> iterator () {return ListIterator (); } public listIterator <e> listIterator (final int index) {checkForComodification (); RangcheckForAdd (index); final int offset = this.offset; return new ListIterator <e> () {int cursor = index; int lastret = -1; int public boolean hasnext () {return cursor! = sublist.this.size; } @SuppressWarnings ("Unchecked") public e suivant () {checkForComodification (); int i = curseur; if (i> = sublist.this.size) jetez un nouveau nosuchementElementException (); Object [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) lancez new concurrentModificationException (); curseur = i + 1; return (e) elementData [offset + (lastret = i)]; } public boolean hasprevious () {return Cursor! = 0; } @SuppressWarnings ("Unchecked") public e précédemment () {checkForComodification (); int i = curseur - 1; if (i <0) lancer un nouveau nosuchementElementException (); Object [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) lancez new concurrentModificationException (); curseur = i; return (e) elementData [offset + (lastret = i)]; } @SuppressWarnings ("Unchecked") public void ForEachRemaining (consommateur <? Super E> Consumer) {objets.RequiRenonnull (consommateur); Final int size = sublist.Chis.Size; int i = curseur; if (i> = size) {return; } objet final [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) {lancez new concurrentModificationException (); } while (i! = size && modCount == attendModCount) {Consumer.Accept ((e) elementData [offset + (i ++)]); } // Mettez à jour une fois à la fin de l'itération pour réduire le trafic d'écriture de tas lastret = cursor = i; checkForComodification (); } public int nextIndex () {return Cursor; } public int promedIndex () {return Cursor - 1; } public void dissovel () {if (lastret <0) lancer un nouveau illégalStateException (); checkForComodification (); essayez {sublist.This.reMove (lastret); Cursor = lastret; lastret = -1; attendModCount = arrayList.this.modCount; } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }} public void set (e e) {if (lastret <0) lance un nouveau illégalStateException (); checkForComodification (); try {arrayList.this.set (offset + lastret, e); } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }} public void add (e e) {checkForComodification (); essayez {int i = curseur; Sublist.This.add (i, e); curseur = i + 1; lastret = -1; attendModCount = arrayList.this.modCount; } catch (indexoutofboundSexception ex) {lancez new concurrentModificationException (); }} final void checkForComodification () {if (attendModCount! = arrayList.this.modCount) New concurrentModificationException (); }}; } public list <e> sublist (int FromIndex, int toindex) {sublistrangeCheck (FromIndex, toindex, size); retourner un nouveau subliste (ce, offset, fromindex, toindex); } private void RangECheck (int index) {if (index <0 || index> = this.size) New indexOutofBoundSexception (uutofboundsmsg (index)); } private void RangECheckForAdd (int index) {if (index <0 || index> this.size) lancez une nouvelle indexoutofboundSexception (uutofboundsmsg (index)); } chaîne privée outofboundsmsg (int index) {return "index:" + index + ", size:" + this.size; } private void checkForComodification () {if (arrayList.this.modCount! = this.modCount) Jetez de nouveaux mododification ConcurrentException (); } public Spliterator <e> Splitterator () {checkForComodification (); Renvoie un nouveau ArraylistPliterator <e> (ArrayList.Te, offset, offset + this.size, this.modCount); }} @Override public void foreach (Consumer <? Super E> Action) {objets.RequiRenonnull (Action); final int attendModCount = modCount; @SuppressWarnings ("non coché") final e [] elementData = (e []) this.elementData; Final int size = this.size; for (int i = 0; modCount == attendModCount && i <size; i ++) {action.accept (elementData [i]); } if (modCount! = attendModCount) {Throw New ConcurrentModificationException (); }} / ** * crée un <em> <a href = "spliterator.html # liant" rel = "externe nofollow"> tardif de contrainte </a> </em> * et <em> fail-fast </em> {@link Spliterator} sur les éléments de cette liste *. * * <p> Le {@code spliterator} reporte {@link Spliterator # size}, * {@link Spliterator # subsized}, et {@link Spliterator # Ordord}. * Les implémentations remplacées devraient documenter le rapport de valeurs caractéristiques supplémentaires. * * @return A {@Code Spliterator} sur les éléments de cette liste * @Since 1.8 * / @Override public Spliterator <e> Splitterator () {return new ArraylistPliterator <> (this, 0, -1, 0); } / ** SPLITATEUR DE CLASSE FINAL SPIST-BY-BY-TWO, LAZY * / Classe finale statique ArraylistsPliterator <E> Implémentez Spliterator <E> {/ * * Si les listes de table étaient immuables, ou structurellement immuables (non * ajouts, suppriment, etc.), nous pourrions mettre en œuvre leurs séparateurs * avec Arrays.Spliterator. Au lieu de cela, nous détectons autant d'interférence pendant la traversée que pratique sans * sacrifier beaucoup de performances. Nous comptons principalement sur * modCounts. Ceux-ci ne sont pas garantis de détecter la violence concurrencée *, et sont parfois trop conservateurs sur * les interférences intra-thread, mais détectent suffisamment de problèmes pour * être utile dans la pratique. Pour y parvenir, nous (1) paresseusement * initialiser la clôture et un montant attendu jusqu'au dernier * point que nous devons nous engager dans l'état que nous vérifions * contre; améliorant ainsi la précision. (Cela ne s'applique pas aux * sublilistes, qui créent des séparateurs avec des valeurs non-paresseuses actuelles). (2) Nous effectuons seulement une seule vérification * concurrentModificationException à la fin de Foreach * (la méthode la plus sensible aux performances). Lorsque vous utilisez ForEach * (par opposition aux itérateurs), nous ne pouvons normalement détecter que les interférences après les actions, pas avant. En outre, les vérifications de déclenchement CME s'appliquent à toutes les autres violences possibles * d'hypothèses par exemple null ou trop à petit * tableau ElementData étant donné sa taille (), qui ne pouvait que * se produire en raison de l'interférence. Cela permet à la boucle intérieure * de ForEach à fonctionner sans autre vérification et * simplifie la résolution lambda. Bien que cela implique un * nombre de vérifications, notez que dans le cas commun de * list.Stream (). ForEach (a), aucune vérification ou autre informatique * ne se produit ailleurs que dans Forach lui-même. Les autres méthodes moins utiles ne peuvent pas profiter de la plupart de * ces ruisseaux. * / LISTE PRIVÉ FINAL ARRAYLIST <E>; Index int privé; // Index actuel, modifié sur la clôture privée à l'avance / division; // -1 jusqu'à utilisation; puis un dernier index Private int attendmodCount; // initialisé lorsque la clôture set / ** Créer un nouveau splitateur couvrant la plage donnée * / ArraylistPliterator (ArrayList <E> List, int Origin, int Fence, int attendModCount) {this.list = list; // ok si null sauf si vous avez traversé ce.index = origine; this.fence = clôture; this.expectedModCount = attendModCount; } private int getFence () {// Initialiser la clôture à la taille sur la première utilisation int hi; // (une variante spécialisée apparaît dans Method ForEach) ArrayList <E> LST; if ((hi = clôture) <0) {if ((lst = list) == null) hi = clôture = 0; else {attendModCount = lst.modCount; hi = clôture = lst.size; }} return Salut; } public arraylistPliterator <e> trysplit () {int hi = getFence (), lo = index, mid = (lo + hi) >>> 1; return (lo> = mid)? null: // diviser la plage de moitié à moins que trop petit ArrayListsPliterator <e> (list, lo, index = mid, attendModCount); } public boolean tryAdvance(Consumer<? super E> action) { if (action == null) throw new NullPointerException(); int hi = getFence(), i = index; if (i < hi) { index = i + 1; @SuppressWarnings("unchecked") E e = (E)list.elementData[i]; action.accept(e); if (list.modCount != expectedModCount) throw new ConcurrentModificationException(); Retour Vrai; } return false; } public void forEachRemaining(Consumer<? super E> action) { int i, hi, mc; // hoist accesses and checks from loop ArrayList<E> lst; Object[] a; if (action == null) throw new NullPointerException(); if ((lst = list) != null && (a = lst.elementData) != null) { if ((hi = fence) < 0) { mc = lst.modCount; hi = lst.size; } else mc = expectedModCount; if ((i = index) >= 0 && (index = hi) <= a.length) { for (; i < hi; ++i) { @SuppressWarnings("unchecked") E e = (E) a[i]; action.accept(e); } if (lst.modCount == mc) return; } } throw new ConcurrentModificationException(); } public long estimateSize() { return (long) (getFence() - index); } public int characteristics() { return Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED; } } @Override public boolean removeIf(Predicate<? super E> filter) { Objects.requireNonNull(filter); // figure out which elements are to be removed // any exception thrown from the filter predicted at this stage // will leave the collection unmodified int removeCount = 0; final BitSet removeSet = new BitSet(size); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { @SuppressWarnings("unchecked") final E element = (E) elementData[i]; if (filter.test(element)) { removeSet.set(i); removeCount++; } } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } // shift surviving elements left over the spaces left by removed elements final boolean anyToRemove = removeCount > 0; if (anyToRemove) { final int newSize = size - removeCount; for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) { i = removeSet.nextClearBit(i); elementData[j] = elementData[i]; } for (int k=newSize; k < size; k++) { elementData[k] = null; // Let gc do its work } this.size = newSize; if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } return anyToRemove; } @Override @SuppressWarnings("unchecked") public void replaceAll(UnaryOperator<E> operator) { Objects.requireNonNull(operator); final int expectedModCount = modCount; final int size = this.size; for (int i=0; modCount == expectedModCount && i < size; i++) { elementData[i] = operator.apply((E) elementData[i]); } if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; } @Override @SuppressWarnings("unchecked") public void sort(Comparator<? super E> c) { final int expectedModCount = modCount; Arrays.sort((E[]) elementData, 0, size, c); if (modCount != expectedModCount) { throw new ConcurrentModificationException(); } modCount++; }}Résumer
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!