Ich habe schon einmal einen Satz gelesen und es war sehr gut. Jemand hat gefragt, was die Verwendung von Quellcode aus dem Lesen aussetzt? Erfahren Sie die Designideen anderer, um eine bestimmte Funktion zu implementieren und Ihre Programmierstufe zu verbessern.
Ja, jeder implementiert eine Funktion. Unterschiedliche Menschen haben unterschiedliche Designideen. Einige Leute verwenden 10.000 Codezeilen und einige Leute verwenden 5.000 Zeilen. Einige Leute müssen den Code für Dutzende von Sekunden ausführen, während andere nur einige Sekunden brauchen. . Kommen wir zum Thema unten.
Hauptinhalt dieses Artikels:
・Ein detaillierter Kommentar zur Implementierung von ArrayList basierend auf JDK 1.8.
・Der Iterator -Sublist -Teil wurde nicht im Detail erläutert und wird in andere Quellcode -Interpretationen platziert. Hier konzentrieren wir uns auf die Implementierung von ArrayList selbst.
°
import Java.util.abstractlist; Import Java.util.Arrays; Import Java.util.bitset; Import Java.util.Collection; Import Java.util.comPparator; importieren java.util.concurrentModificationException; java.util.nosuchelementException; import java.util.objects; import Java.util.randomaccess; import Java.util.spliterator Java.util.function.Consumer; der Listenschnittstelle, die geändert werden kann. Implementieren Sie alle optionalen Listenvorgänge und lassen Sie alle Elemente, einschließlich Null, wiederholbar. * Zusätzlich zur Listenschnittstelle bietet diese Klasse eine Möglichkeit, die Größe des Arrays zu manipulieren, um die Größe des Arrays in der Liste zu speichern. * * Zeitkomplexität: * Die Aufrufe zur Methodengröße, Isempty, Get, Set, Iterator und Listiterator sind konstante Zeit. * Die zeitliche Komplexität des Hinzufügens und Löschens ist O (n). Alle anderen Operationen sind lineare Zeitkomplexität. * * Kapazität: * Jede ArrayList hat Kapazität, und die Kapazitätsgröße beträgt mindestens die Länge des Listenelements, und die Standardinitialisierung beträgt 10. * Die Kapazität kann automatisch erhöht werden. * Wenn Sie im Voraus wissen, dass es im Array viele Elemente gibt, können Sie die Kapazität im Voraus erhöhen, indem Sie die Methode zur Sicherung () aufrufen, bevor sie Elemente hinzufügen, um den Aufwand des automatischen Kapazitätswachstums in der späteren Zeit zu verringern. * Diese Kapazität kann auch durch einen Konstruktor mit anfänglicher Kapazität initialisiert werden. * * Thread ist nicht sicher: * ArrayList ist kein Thread sicher. * Wenn es auf Multithreads angewendet werden muss, muss die Synchronisation extern durchgeführt werden * * ModCount: * Definiert in AbstractList: Protected Transient int modcount = 0; * Häufig wurde diese Liste strukturell modifiziert. Die strukturelle Modifikation bezieht sich auf die Änderung der Größe der Liste oder die Störung der Liste, sodass die laufende Iteration falsche Ergebnisse liefert. * Dieses Feld wird von den Iterator- und List -Iterator -Implementierungen verwendet, die von den Iterator- und Listerator -Methoden zurückgegeben werden. * Wenn der Wert in diesem Feld versehentlich geändert wird, wirft der Iterator (oder die Listen -Iterator) eine ConcurrentModificationException als Antwort auf als nächstes aus, entfernen, vorher, festgelegt oder hinzufügen Operationen hinzufügen. * Bei gleichzeitigen Modifikationen während der Iterationen bietet es ein schnelles Verhalten und nicht mit nicht deterministischem Verhalten. * Ob die Unterklasse dieses Feld verwendet, ist optional. * Wenn die Unterklasse einen schnellen Iterator (und Listen -Iterator) bereitstellen möchte, fügt sie dieses Feld einfach zu den Methoden hinzufügen (int, e) und entfernen (int) (und alle anderen Methoden, die sie überschreiben, was zu Modifikationen in der Listenstruktur führt). * Die Anzahl der einzelnen Aufrufe zum Hinzufügen (int, e) oder entfernen (int) darf 1 zu diesem Feld nicht überschreiten, da der Iterator (und Listen -Iterator) eine gefälschte ConcurrentModificationExceptions auswirkt. * Wenn eine Implementierung keinen schnellen Iterator bereitstellen möchte, kann dieses Feld ignoriert werden. * * Transient: * Standardmäßig werden alle Mitgliedsvariablen eines Objekts bestehen. In einigen Fällen können Sie das transiente Schlüsselwort verwenden, um sie zu markieren, um sie zu markieren. Dies ist auch ein reserviertes Wort in Java (JDK 1.8) */Public Class ArrayList erweitert <e> erweitert die abstrakte AbstractList <e> implements list <e>, zufällige, long serialversionsable, java.io.Serializierbares {privatalisierungsabend {private -edatal -endgültige endgültige endgültige endgültige endgültige endgültige endgültige endgültige endgültige serialversionu. 8683452581122892189L; // Standardkapazität privat statische endgültige int default_capacity = 10; // wird verwendet, um leere Array -Instanzen mit leeren Instanzen zu teilen. privates statisches endgültiges Objekt [] leere_elementData = {}; // Standard leeres Array privates statisches endgültiges Objekt [] defaultCapacity_Empty_elementData = {}; // Für das Recht werden die Elemente, Packungszugriffsberechtigungen, transientes Objekt [] elementData gespeichert; // Größe initialisiert Java Int in 0, wenn eine private int -Größe ein Objekt erstellt wird. // Setzen Sie den Konstruktor der Initialisierungskapazität mit der angegebenen Zahl, und die negative Nummer wirft eine öffentliche Ausnahme -ArrayList (int initialCapacity) {if (initialCapacity> 0) {this.elementData = neues Objekt [initialCapacity] aus; } else if (initialCapacity == 0) {this.elementData = leer_elementData; } else {werfen neuer illegalArgumentException ("illegale Kapazität:"+initialCapacity); }} // Default Constructor, verwenden Sie das Kontrollarray, um public arrayList () {this.elementData = DefaultCapacity_Empty_ElementData initialisieren; } // Erstellen Sie eine Liste, die Elemente in der Sammlung in der Reihenfolge der Iteratorrückgabe der Sammlung öffentliche ArrayList enthält (Sammlung <? Erweitert E> c) {elementData = C.toarray (); if ((size = elementData.Length)! } else {// Verwenden Sie ein leeres Array this.elementData = leer_elementData; }} //, weil die Kapazität oft größer ist als die tatsächliche Anzahl von Elementen. Wenn der Speicher eng ist, können Sie diese Methode aufrufen, um den reservierten Standort zu löschen und die Kapazität an die tatsächliche Anzahl der Elemente anzupassen. // Wenn Sie sicher sind, dass keine Elemente hinzugefügt werden, können Sie diese Methode auch aufrufen, um Space public void trimTosize () {modcount ++ zu sparen; if (size <elementData.length) {elementData = (size == 0)? Leere_elementData: arrays.copyof (elementData, Größe); }} // Array -Kapazität mit angegebenen Parametern öffentliche void -Sicherung (int mincapacity) {// Wenn das Array leer ist, prefetch 0, ansonsten zum Standardwert (10) int Minexpand = (elementData! 0: default_capacity; // Wenn der Parameter größer als die voreingestellte Kapazität ist, verwenden Sie diesen Parameter, um die Array -Kapazität weiter einzustellen, wenn (mincapacity> minexpand) {safeExPlicitCapacity (Mincapacity); }} // Stellen Sie beim Hinzufügen von Elementen sicher, dass die Array -Kapazität private void -SeealCapacityInternal (int mincapacity) {// den Standardwert und den größeren Parameter als Kapazitätsvoreinstellung verwenden if (elementData == defaultCapacity_empty_elementdata) {mincapacity = math.max (default_capacity, mincapacity). } sorgenexplicitCapacity (mincapacity); } // Wenn der Parameter größer als die Array -Kapazität ist, erhöhen Sie die Array -Kapazität privat void sorgenexplicitCapacity (int mincapacity) {modcount ++; if (mincapacity - elementData.length> 0) wachsen (mincapacity); } // Die maximale Kapazität des Arrays kann den Speicherüberlauf (VM -Speichergrenze) verursachen. // Erhöhen Sie die Kapazität, um sicherzustellen, dass mindestens die Anzahl der durch den Parameter privaten Hohlraum wachsen (int mincapacity) angegebenen Elemente {int oldCapacity = elementData.length; // Erhöhen Sie die voreingestellte Kapazität um die Hälfte von NewCapacity = OldCapacity + (OldCapacity >> 1); // Nehmen Sie den größeren Wert aus dem Parameter, wenn (Newcapacity - Mincapacity <0) // dh Newcapacity <mincapacity Newcapacity = mincapacity; // Wenn der voreingestellte Wert größer als das Standardmaximum ist, prüfen Sie, ob er überläuft, wenn (NewCapacity - max_array_size> 0) newCapacity = Hugcapacity (Mincapacity); elementData = arrays.copyof (ElementData, NewCapacity); } // Überprüfen Sie, ob es überläuft. Wenn kein Überlauf vorliegt, geben Sie den maximalen Ganzzahlwert zurück (der int in Java beträgt 4 Bytes, so dass das Maximum 0x7ffffffffs beträgt) oder der Standardwert für private statische statische Hugenkapazität (int mincapacity) {if (mincapacity <0) // Überlauf -Wurf -Wurf -Wurf -Wurf -OutofmemoryError (); return (mincapacity> max_array_size)? Integer.max_value: max_array_size; } // Rückgabe die Array -Größe public int size () {return size; } // ist es leer public boolean isEmpty () {return size == 0; } // Ob es eine Nummer enthält, return bool public boolean enthält (Objekt o) {return indexof (o)> = 0; } // geben einen Wert beim ersten Erscheinen des Arrays zurück, und er wird auf unterschiedliche Weise beurteilt, basierend darauf, ob es sich um Null handelt. Wenn es nicht existiert, gibt es -1 zurück. Die Zeitkomplexität ist o (n) public int indexof (Objekt o) {if (o == null) {für (int i = 0; i <size; i ++) if (elementData [i] == null) return i; } else {für (int i = 0; i <size; i ++) if (o.equals (elementData [i]) return i; } return -1; } // Geben Sie zum letzten Mal einen Wert zurück, wenn er im Array angezeigt wird. Wenn es nicht existiert, gibt es -1 zurück. Zeitkomplexität ist o (n) public int lastIndexof (Objekt o) {if (o == null) {für (int i = size-1; i> = 0; i--) if (elementData [i] == null) return i; } else {für (int i = size-1; i> = 0; i--) if (o.equals (elementData [i]) return i; } return -1; } // Die Kopie zurückgibt, wurde das Element selbst nicht kopiert, und eine Ausnahme wird ausgelöst, wenn das Array des Kopierprozesses öffentlich Objekt Clone () {try {ArrayList <> v = (ArrayList <>) Super.clone () ändert; v.ElementData = arrays.copyof (elementData, Größe); v.modcount = 0; Rückkehr v; } catch (clonenotsuptedEdException e) {neue interne ERError werfen (e); }} // In ein Objektarray konvertieren, verwenden Sie die Arrays.copyof () Methode Public Object [] toArray () {return arrays.copyof (ElementData, Größe); } // Ein Array zurückgeben, verwenden Sie die Laufzeit, um den Typ zu bestimmen, und das Array enthält alle Elemente in dieser Liste (vom ersten bis zum letzten Element) // Die zurückgegebene Array -Kapazität wird durch die Parameter und den größeren Wert in diesem Array @Suppresswarnings ("deaktiviert") bestimmt. Arrays.copyof (ElementData, Größe, A.getClass ()); System.ArrayCopy (elementData, 0, a, 0, Größe); if (a.länge> Größe) a [Größe] = null; Rückkehr a; } // Gibt den Wert der angegebenen Position zurück, da es sich um ein Array handelt, es ist besonders schnell @SuppressWarnings ("deaktiviert") e elementData (int Index) {return (e) elementData [index]; } // den Wert der angegebenen Position zurückgeben, aber prüfen Sie, ob die Anzahl der Positionen die Array -Länge öffentlich e get (int Index) {rangecheck (index) überschreitet; returnelementData (Index); } // Setzen Sie die angegebene Position auf einen neuen Wert und senden Sie den vorherigen Wert zurück, prüfen Sie, ob diese Position die Array -Länge öffentlich E -Set (int Index, E -Element) {rangecheck (index) überschreitet. E oldValue = elementData (index); elementData [index] = element; kehren Sie OldValue zurück; } // Fügen Sie zuerst einen Wert hinzu, der zuerst die Kapazität öffentliche boolean add (e e) {sealEcapacityInternal (Größe + 1); ElementData [Größe ++] = e; zurückkehren; } // einen Wert in der angegebenen Position hinzufügen und die hinzugefügte Position und die Kapazität public void add (int Index, E -Element) {rangecheckForAdd (Index) addieren; sealEcapacityInternal (Größe + 1); // Public static void ArrayCopy (Objekt SRC, int srcpos, Objektdest, int destpos, int länge) // src: Quellarray; SRCPOS: Die Startposition des zu kopierten Quellarrays; Ziel: Zielarray; destpos: die Ausgangsposition des Zielarrays; Länge: Kopieren Sie Länge System.ArrayCopy (ElementData, Index, ElementData, Index + 1, Größe - Index); elementData [index] = element; Größe ++; } // Löschen Sie den Wert der angegebenen Position, überprüfen Sie die hinzugefügte Position und senden Sie den vorherigen Wert public e entfernen (int Index) {rangecheck (index); ModCount ++; E oldValue = elementData (index); int nummoved = Größe - Index - 1; if (nummoved> 0) system ElementData [-Größe] = NULL; // Einfach zu recyceln der Müllsammlungsperiode Return OldValue; } // Löschen Sie den Ort, an dem das angegebene Element zuerst öffentlich boolean entfernen (Objekt o) {if (o == null) {für (int index = 0; index <size; index ++) if (elementData [index] == null) {fastReMove (index); zurückkehren; }} else {for (int index = 0; index <size; index ++) if (o.equals (elementData [index])) {fastremove (index); zurückkehren; }} return false; } // Löschen Sie den Wert schnell an der angegebenen Position. Der Grund, warum es schnell bezeichnet wird, sollte sein, dass es nicht erforderlich ist, den Wert zu überprüfen und zurückzugeben, da nur private void fastremove (int index) {modcount ++; int nummoved = Größe - Index - 1; if (nummoved> 0) system ElementData [-Größe] = NULL; // Löschen, um GC seine Arbeit zu erledigen} // Das Array löschen und jeden Wert auf Null setzen, um die Müllsammlung zu erleichtern (im Gegensatz zum Zurücksetzen wird die Standardgröße des Arrays nicht zurückgesetzt, wenn es ändert) öffentlich void clear () {modcount ++; für (int i = 0; i <size; i ++) elementData [i] = null; Größe = 0; } // Fügen Sie am Ende ein Element einer Sammlung hinzu, wenn die zugefügte Sammlung leer ist, geben Sie falsche öffentliche Boolesche Addall zurück (Sammlung <? Erweitert E> c) {Objekt [] a = C.toarray (); int numnew = A.Length; sealEcapacityInternal (Größe + numnew); System.ArrayCopy (a, 0, elementData, Größe, Numnew); Größe += numnew; return numnew! = 0; } // Die Funktion ist die gleiche wie oben, fügen Sie öffentliches boolean addall hinzu (int Index, Sammlung <? Erweitert E> c) {rangecheckForAdd (Index); Objekt [] a = c.toarray (); // das zu hinzugefügte Array in numnew = A.Length; // die Länge des Arrays, das die äatelische Kapazität hinzugefügt werden soll (Größe + Numnew); // Die Kapazität int nummoved = Größe - Index; // Die Länge, die sich nicht verschiebt (der vorherige Teil), wenn (nummoved> 0) // Wenn es nicht verschoben werden muss, kopieren Sie es von selbst und verschieben Sie den hinteren Teil des Arrays auf das richtige Positionssystem.ArrayCopy (ElementData, Index, ElementData, Index + Numnew, nummed, nummed). System.ArrayCopy (A, 0, ElementData, Index, Numnew); // Neues Array in die Mitte der geänderten ursprünglichen Arraygröße += numnew hinzufügen; return numnew! = 0; } // Löschen Sie das angegebene Bereichselement. Die Parameter sind die geschützten Start- und Endpositionen geschütztes Void -Entferner (int vonIndex, int toIndex) {modCount ++; int nummoved = Größe - toIndex; // Die Länge, die vom letzteren Abschnittssystem beibehalten wird. int newSize = Größe - (toIdex -fromIdex); für (int i = newSize; i <size; i ++) {elementData [i] = null; } size = newSize; } // Überprüfen Sie, ob die Zahl die Länge des Arrays beim Hinzufügen von Elementen privat void rangecheck (int index) {if (index> = size) wirf einen neuen IndexoutOfBoundSexception (outofBoundSMSG (Index))); } // Überprüfen Sie, ob private void rangecheckForAdd (int Index) {if (index> Größe || index <0) neue IndexoutOfBoundSexception (outofBoundSMSG (Index))); } // Details der geworfenen Ausnahme private Zeichenfolge outOfBoundSmsg (int index)) {return "Index:"+index+", Größe:"+Größe; } // Löschen Sie das Element der angegebenen Sammlung public boolean removeall (Sammlung <?> C) {Objects.requirenonnull (c); // Überprüfen Sie, ob der Parameter null return batchremove (c, false); } // behalten Sie nur die Elemente der angegebenen Sammlung öffentlich boolean retainall (Sammlung <?> C) {Objects.requirenonnull (c); return batchremove (c, true); }/** * Quellcode -Interpretation von http://anxpp.com/ * @param complete Wenn wahr, wird der Wert des Elements in der angegebenen Sammlung vom Array beibehalten, und wenn falsch, wird der Wert des Elements in der angegebenen Sammlung aus dem Array gelöscht. * @return Die doppelten Elemente im Array werden gelöscht (anstatt nur ein- oder mehrmals gelöscht), und jeder Löschvorgang wird true zurückgegeben. int r = 0, w = 0; boolean modified = false; Versuchen Sie es mit {// transweep durch das Array und überprüfen Sie, ob diese Sammlung den entsprechenden Wert enthält, den Wert an die Vorderseite des Arrays, und der letzte Wert von W ist die Anzahl der zu erhaltenen Elemente // Einfacher Punkt: Wenn beibehalten wird, verschieben Sie das gleiche Element in den vorherigen Abschnitt. Wenn Sie gelöscht werden, bewegen Sie verschiedene Elemente in den vorherigen Abschnitt für (; r <size; r ++) if (c.contains (elementData [r]) == komplement) elementData [w ++] = elementData [r]; } Endlich {// Stellen Sie sicher, dass der Teil vor der Ausnahme die erwartete Operation abschließen kann, während der Teil, der nicht durchquert wurde, mit der Rückseite verbunden ist // r! = Größe bedeutet, dass ein Fehler auftreten kann: C.Contains (elementData [r]) wirft eine Ausnahme aus, wenn (r! W += Größe - R; } // Wenn w == Größe: bedeutet, dass alle Elemente beibehalten werden, sodass kein Löschvorgang auftritt, so dass falsch zurückgegeben wird. Ansonsten ist wahr und das Array // Wenn w! = Größe zurückgegeben wird, auch wenn der Try -Block eine Ausnahme ausgelöst wird, wird die Operation vor der Ausnahme ausgelöst, da W immer die Länge des vorherigen Teils ist und das Array nicht aus der Reihenfolge ist, weil (w! = Größe) {für (int i = w; i <grise; i ++) elementdata [i] = null; ModCount += Größe - W; // Die Anzahl der Zeiten verändert die Größe = W; // Die neue Größe ist die Anzahl der Elemente, die modified = true erhalten sind; }} return modifiziert; } // Speichern Sie den Status der Array -Instanz in einem Stream (dh er ist serialisiert). Das Schreibprozess -Array wird geändert und eine Ausnahme wird private void writeObject (java.io.objectoutputStream s) ausgelöst. S.DefaultWriteObject (); // Führen Sie den Standardprozess für Deserialisierung/Serialisierung aus. Schreiben Sie nicht statische und nicht-transitorische Felder der aktuellen Klasse in diesen Stream // Schreiben Sie in die Größe S.WriteInt (Größe); // alle Elemente schreiben, um (int i = 0; i <size; i ++) {S.WriteObject (elementData [i]); } if (modcount! }} // Das obige wird geschrieben, dies wird gelesen. private void readObject (java.io.objectinputStream s) löst java.io.ioException, classNotFoundException {elementData = leer_elementData aus; // Führen Sie den Standard -Serialisierungs-/Deserialisierungsprozess s.defaultreadObject () durch; // In der Array -Länge S.Readint () lesen; if (size> 0) {sealEcapacityInternal (Größe); Objekt [] a = elementData; // In allen Elementen lesen (int i = 0; i <size; i ++) {a [i] = s.ReadObject (); }}}} // Rückgabe -Listiterator, die Startposition ist der angegebene Parameter Public Listiterator <E> Listiterator (int index) {if (index <0 || index> Größe) Wirf neu indexoutOfBoundSexception ("Index:"+index); Neue Listitr (Index) zurückgeben; } // Rückkehr Listiterator, die Startposition ist 0 public Listiterator <E> listiterator () {Neue Listitr zurückgeben (0); } // ordentliche Iterator public iterator <e> iterator () {neuer itr () zurückgeben; } // Der allgemeine Iterator implementiert die private Klasse ITR implementiert Iterator <E> {int Cursor; // Der Cursor, der Index des nächsten Elements, die Standardinitialisierung ist 0 int lastret = -1; // Die Position des zuletzt zugegriffenen Elements ist int erwartetModcount = modcount; // Der Iterationsprozess wird das modifizierte Array nicht ausgeführt. Andernfalls wird eine Ausnahme ausgelöst // Gibt es einen weiteren öffentlichen booleschen hasNext () {return Cursor! = Größe; } // Das nächste Element @SuppressWarnings ("Deaktiviert") public e next () {techeforComodification (); // Überprüfen Sie, ob das Array int i = cursor geändert wird; if (i> = size) werfen neue noSuchelementException (); Object [] elementData = arrayList.this.ElementData; if (i> = elementData.length) werfen neue ConcurrentModificationException (); Cursor = i + 1; // Bewegen Sie den Cursor rückwärts zurück (e) elementData [lastret = i]; // Setzen Sie die Zugriffsposition und geben Sie diesen Wert zurück} // Löschen Sie das Element public void remove () {if (lastret <0). checkforComodification (); // prüfen Sie, ob das Array geändert wird, try {ArrayList.this.remove (lastret); Cursor = Lastret; Lastret = -1; erweitertModcount = modcount; } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }} @Override @SuppressWarnings ("Deaktiviert") public void for reachRemaining (Verbraucher <? Super e> Verbraucher) {Objects.requirenonnull (Verbraucher); endgültige int size = arrayList.this.Size; int i = cursor; if (i> = size) {return; } Final Object [] elementData = arrayList.this.ElementData; if (i> = elementData.length) {werfen Sie eine neue ConcurrentModificationException (); } while (i! = size && modcount == erwartungsgemodcount) {Consumer.accept ((e) elementData [i ++]); } cursor = i; lastret = i - 1; checkforComodification (); } // Überprüfen Sie, ob das Array endgültig modifiziert wird. }} // ListIterator Iterator implementiert private Klasse Listitr erweitert ITR implementiert ListItIterator <E> {listitr (int index) {super (); Cursor = index; } public boolean hasprevious () {return cursor! = 0; } public int nextIndex () {return cursor; } public int PrevotIndex () {Return Cursor - 1; } @SuppressWarnings ("deaktiviert") public e vorher () {CheckForComodification (); int i = cursor - 1; Wenn (i <0) neue NoSuchelementException () werfen; Object [] elementData = arrayList.this.ElementData; if (i> = elementData.length) werfen neue ConcurrentModificationException (); Cursor = i; return (e) elementData [lastret = i]; } public void set (e e) {if (lastret <0) werfen neue illegaleStateException (); checkforComodification (); try {arrayList.this.set (lastret, e); } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }} public void add (e e) {checkforComodification (); Versuchen Sie {int i = cursor; ArrayList.this.Add (i, e); Cursor = i + 1; Lastret = -1; erweitertModcount = modcount; } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }}} // RECHTSUMMER DER SUBERAURAY des angegebenen Bereichs Public List <E> Sublist (int vonIndex, int toIndex) {sublistangecheck (von INDEX, TOINDEX, Größe); Rückkehr neuer Sublisten (dies, 0, von iNdex, nach Index); } // Sicherheitsprüfung statische void sublistangecheck (int vonIndex, int toIdex, int size) {if (von iNdex <0) Wirf eine neue IndexoutOfBoundSexception ("fromIndex =" + fromIndex); if (toIndex> Größe) neue IndexoutOfBoundSexception ("toIndex =" + toIndex) werfen; if (von iNdex> toIdex) werfen neue illegalArgumentException ("von iNidEx (" + von index + ")> toIdex (" + toIdex + ")"); } // SubaRray Private Class Sublist erweitert AbstractList <E> implementiert RandomAccess {private final AbstractList <e> übergeordnet; private endgültige int parentOffset; privates Final INT -Offset; int Größe; Sublist (AbstractList <E> übergeordnet, int offset, int vonIndex, int toIndex) {this.Parent = parent; this.ParentOffset = von iNdex; this.offset = offset + von iNdex; this.size = toIndex - von iNdex; 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; kehren Sie OldValue zurück; } public e get (int index) {rangecheck (index); checkforComodification (); return arrayList.this.elementData (Offset + Index); } public int size () {CheckforComodification (); kehre dies zurück. } public void add (int index, e e) {rangecheckForAdd (index); checkforComodification (); parent.add (parentOffset + index, e); this.modcount = parent.modcount; this.size ++; } public e remove (int index) {rangecheck (index); checkforComodification (); E result = parent.remove (parentOffset + index); this.modcount = parent.modcount; this.size--; Rückgabeergebnis; } protected void removerange (int vonIndex, int toIndex) {CheckforComodification (); parent.removerange (parentOffset + von iNdex, parentOffset + toIdex); this.modcount = parent.modcount; this.size - = toIndex - von iNdex; } public boolean addall (Sammlung <? Erweitert E> c) {return addall (this.size, c); } public boolean addall (int index, sammeln <? erweitert 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; zurückkehren; } public iterator <e> iterator () {return listIterator (); } public listIterator <e> listiterator (endgültiger intindex) {techeforComodification (); rangecheckForAdd (Index); endgültig int offset = this.offset; Neue Listiterator <E> () {int cursor = index zurückgeben; int lastret = -1; int erweitertmodcount = arrayList.this.modcount; public boolean hasNext () {return cursor! = sublist.this.size; } @SuppressWarnings ("deaktiviert") public e next () {checkforComodification (); int i = cursor; if (i> = sublist.this.size) werfen neue noSuchelementException (); Object [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) werfen neue ConcurrentModificationException (); Cursor = i + 1; return (e) elementData [Offset + (lastret = i)]; } public boolean hasprevious () {return cursor! = 0; } @SuppressWarnings ("deaktiviert") public e vorher () {CheckForComodification (); int i = cursor - 1; Wenn (i <0) neue NoSuchelementException () werfen; Object [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) werfen neue ConcurrentModificationException (); Cursor = i; return (e) elementData [Offset + (lastret = i)]; } @SuppressWarnings ("Deaktiviert") public void forReRemaining (Verbraucher <? Super e> Verbraucher) {Objects.requirenonnull (Verbraucher); endgültige int size = sublist.dis.Size; int i = cursor; if (i> = size) {return; } Final Object [] elementData = arrayList.this.ElementData; if (offset + i> = elementData.length) {neue ConcurrentModificationException (); } while (i! = size && modCount == erwartungsgemodcount) {Consumer.accept ((e) elementData [Offset+(i ++)]); } // Update einmal am Ende der Iteration, um Heap -Verkehrsverkehr Lastret = Cursor = i; checkforComodification (); } public int nextIndex () {return cursor; } public int PrevotIndex () {Return Cursor - 1; } public void remove () {if (lastret <0) werfen neue illegaleStateException (); checkforComodification (); try {sublist.this.remove (lastret); Cursor = Lastret; Lastret = -1; erweitertModcount = arrayList.this.modcount; } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }} public void set (e e) {if (lastret <0) werfen neue illegaleStateException (); checkforComodification (); try {arrayList.this.set (offset + lastret, e); } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }} public void add (e e) {checkforComodification (); Versuchen Sie {int i = cursor; Sublist.this.add (i, e); Cursor = i + 1; Lastret = -1; erweitertModcount = arrayList.this.modcount; } catch (indexoutOfboundSexception ex) {neue ConcurrentModificationException (); }} endgültig void checkForComodification () {if (erwarteteModcount! }}; } public list <e> sublist (int vonIndex, int toIndex) {sublistangecheck (von iNdex, toIdex, Größe); Neue Unterliste zurückgeben (dies, Offset, von iNdex, nach Index); } private void rangecheck (int index) {if (index <0 || index> = this.size) Wirf neu IndexoutOfBoundSexception (outofboundSmsg (index)); } private void rangecheckForAdd (int index) {if (index <0 || index> this.size) Wirf neu IndexoutOfBoundSexception (outofboundSMSG (Index)); } private String outOfBoundSmsg (int index) {return "Index:"+index+", Größe:"+this.size; } private void checkforComodification () {if (arrayList.this.modcount! } public Splaster <E> splitterator () {checkforComodification (); RECHTEN SIE NEURARAYLISTERSPLITIRATOR <E> (ArrayList.This, Offset, Offset + this.size, this.modcount); }} @Override public void foreach (Consumer <? Super e> Aktion) {Objects.requirenonnull (Aktion); endgültig int erweitertmodcount = modcount; @SuppressWarnings ("Deaktiviert") endgültig e [] elementData = (e []) this.elementData; endgültige int size = this.size; für (int i = 0; modcount == erwartungsgemodcount && i <size; i ++) {action.accept (elementData [i]); } if (modcount! }}/** * erstellt ein <em> <a href = "Splatter .html#binding" rel = "external nofollow"> Late-Binding </a> </em> * und <em> fail-fast-fast-fast </em> {@link Sprecher} über die Elemente in dieser * Liste in dieser * Liste. * * <p> Der {@code -Splitter} berichtet {@link Sprecher#Size}, * {@link Sprecher#subsized} und {@link Splitterer#ordnungsgemäß}. * Übergeordnete Implementierungen sollten die Berichterstattung zusätzlicher * charakteristischer Werte dokumentieren. * * @return a {@Code Sprecher} über die Elemente in dieser Liste * @Since 1.8 */ @Override public Splitter <e> splitterator () {NeuarrayListSPliterator <> (this, 0, -1, 0); } /** indexbasiertes Split-by-Two, Lazy Initialisierter Splitter * /statische endgültige KlassenarraylistsPliterator <E> implementiert Splitter <E> { / * *, wenn Arraylisten unveränderlich waren oder strukturell unveränderlich (no * hinzugefügt, addiert, entfernt, usw.), können wir ihre Splitterer implementieren * mit Arrays mit Arrays. Stattdessen erkennen wir so viel * Einmischung während des Durchquerens wie praktisch, ohne viel Leistung zu opfern. Wir verlassen uns hauptsächlich auf * modcounts. Es ist nicht garantiert, dass diese Gewalt auf Parallelastung erkennen und manchmal übermäßig konservativ in Bezug auf die Störung des Threads, sondern genügend Probleme erkennen, um sich in der Praxis zu lohnen. Um dies auszuführen, initialisieren wir (1) faul * Zaun und erwartungsgemäß, bis zum letzten Punkt *, gegen den wir uns für den Staat verpflichten müssen, gegen den wir überprüft werden, gegen; So verbessern Sie die Präzision. (Dies gilt nicht für * Sublisten, die Splitteratoren mit aktuellen nicht-faulen Werten erzeugen). (2) Wir führen am Ende von foreach * nur eine einzelne * ConcurrentModificationException-Prüfung (die am leistungsempfindlichsten Methode). Bei Verwendung von foreach * (im Gegensatz zu Iteratoren) können wir normalerweise nur Interferenzen nach den Handlungen erkennen, nicht vorher. Weiter gelten * CME-Trigger-Überprüfungen für alle anderen möglichen * Gewalt von Annahmen, z. Dadurch kann die innere Schleife * von foreach ohne weitere Überprüfungen ausgeführt werden, und * vereinfacht die Lambda-Auflösung. Während dies eine * Anzahl von Schecks beinhaltet, beachten Sie, dass im gemeinsamen Fall von * list.stream (). Foreach (a) keine Schecks oder andere Computer * überall als innerhalb von Foreach auftreten. Die anderen * weniger ausgewählten Methoden können die meisten dieser Streamlinings nicht nutzen. */ private Final ArrayList <E> Liste; privater Int -Index; // aktueller Index, geändert auf Advance/Split Private Int Zaun; // -1 bis verwendet; dann eine vergangene letzte Index privat int erweitertmodcount; // initialisiert, wenn Zaun festgelegt wird/ ** Neuen Splitter erstellen, das den angegebenen Bereich abdeckt // ok wenn null, es sei denn, dies durchquerte. Index = Origin; this.fence = Zaun; this.expectedModcount = erwartungsgemodcount; } private int Getfence () {// Zaun initialisieren, um zuerst int Hi; // (eine spezialisierte Variante erscheint in der Methode foreach) ArrayList <e> lst; if ((hi = fence) <0) {if ((lst = list) == null) hi = fence = 0; sonst {erwarteteModcount = lst.modcount; hi = zaun = lst.size; }} return hi; } public arrayListSpliterator <E> trysplit () {int hi = getfence (), lo = index, Mid = (lo + hi) >>> 1; return (lo> = mid)? NULL: // Divide Range in zwei Hälften, es sei denn, zu kleinen NeuarraylistsPliterator <E> (Liste, lo, index = mid, erwartungsgemodcount); } 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(); zurückkehren; } 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++; }}Zusammenfassen
The above is all about ArrayList source code analysis in Java programming, and I hope it will be helpful to everyone. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!