Ich habe vor 2 Monaten einen Blog-Beitrag zum Thema geschrieben. Der Artikel ist für C #, List<T>
aber Java ArrayList
hat eine sehr ähnliche Implementierung. Da ArrayList
es mithilfe eines dynamischen Arrays implementiert wird, nimmt es bei Bedarf an Größe zu. Der Grund für den Kapazitätskonstruktor liegt also in Optimierungszwecken.
Wenn eine dieser Größenänderungsvorgänge ausgeführt wird, kopiert die ArrayList den Inhalt des Arrays in ein neues Array, das doppelt so groß ist wie das alte. Diese Operation läuft in O (n) Zeit.
Beispiel
Hier ist ein Beispiel, wie sich die ArrayList
Größe erhöhen würde:
10
16
25
38
58
... 17 resizes ...
198578
297868
446803
670205
1005308
Die Liste beginnt also mit einer Kapazität von 10
: Wenn das 11. Element hinzugefügt wird, wird es um 50% + 1
bis erhöht 16
. Ab dem 17. Punkt ArrayList
wird der Wert erneut erhöht 25
und so weiter. Betrachten Sie nun das Beispiel, in dem wir eine Liste erstellen, in der die gewünschte Kapazität bereits als bekannt ist 1000000
. Wenn Sie den ArrayList
Konstruktor ohne Größe erstellen, werden ArrayList.add
1000000
Zeiten aufgerufen , die normalerweise O (1) oder O (n) beim Ändern der Größe benötigen.
1000000 + 16 + 25 + ... + 670205 + 1005308 = 4015851 Operationen
Vergleichen Sie dies mit dem Konstruktor und rufen Sie dann auf, ArrayList.add
was garantiert in O (1) ausgeführt wird .
1000000 + 1000000 = 2000000 Operationen
Java vs C #
Java ist wie oben und beginnt bei 10
und erhöht jede Größenänderung bei 50% + 1
. C # beginnt bei 4
und steigt viel aggressiver an und verdoppelt sich bei jeder Größenänderung. Das 1000000
Beispiel von oben für C # verwendet 3097084
Operationen.
Verweise