JavaRush /Java-Blog /Random-DE /new ArrayList(????) wie und wo ist es besser zu initialis...
Vovan
Level 22

new ArrayList(????) wie und wo ist es besser zu initialisieren

Veröffentlicht in der Gruppe Random-DE
Code zu schreiben, ohne das Collections-Framework zu verwenden , wäre verrückt. Dies ist ein wunderbares Stück Java mit vielen netten Lösungen. Noch wichtiger ist, dass Sie sich im Gegensatz zu Arrays keine Gedanken über die Größe machen müssen. Die ArrayList wächst, bis ihr der Speicher ausgeht. Der Entwickler muss sich nicht um die Anfangsgröße und den ArrayIndexOutOfBoundsException- Fehler kümmern . Was aber, wenn es eine Bedingung zur Überwachung der Speichermenge gibt? Können wir den Speicher bei der Arbeit mit Sammlungen effizient nutzen?
Es stellt sich eine Standardfrage: Wie initialisiert man eine Liste? Der folgende Code funktioniert nicht: Es kommt zu einem Kompilierungsfehler: Die lokalen Variablennamen wurden möglicherweise nicht initialisiert . Die Java-Spezifikation erfordert, dass alle lokalen Variablen (die auf dem Stapel vorhanden sind) mit entsprechenden Werten initialisiert werden. So geht's: Die Liste muss unbedingt initialisiert werden. Sie können die Liste entweder in der ersten Zeile erstellen oder etwas Intelligenteres tun und eine verzögerte Initialisierung verwenden , wie wir es bei der Methode getAllNames() getan haben . In diesem Fall wird die Liste nur bei Bedarf erstellt. Wenn die Anfangsbedingungen nicht erfüllt sind, wird die Liste niemals auf dem Heap angezeigt. Hier kommen wir zur Hauptfrage: Welche Größe sollten wir für die Liste festlegen? Am besten geben Sie ihm die genaue Größe an. Beispiel: In diesem Fall müssen genau n Namen zurückgegeben werden und als Konsequenz wird eine Sammlung von n Elementen erstellt. Allerdings ist der genaue Wert von n nicht immer bekannt. Was wäre, selbst im gegebenen Beispiel, wenn n=1000 und nur 100 Namen verfügbar wären? Bei der Arbeit mit Sammlungen besteht die beliebteste Methode darin, den Standardkonstruktor aufzurufen. Wenn Sie sich den Java-Quellcode (Version 1.6) ansehen , wird standardmäßig eine Liste mit 10 Elementen erstellt . Das heißt, wir können den Standardkonstruktor sicher verwenden, wenn wir nicht vorhaben, mehr als 10 Elemente in der Liste zu speichern. Was passiert, wenn Sie versuchen, das 11. Element hinzuzufügen? Nun, nichts Schlimmes ... das Element wird erfolgreich hinzugefügt. Schauen Sie sich die Methode an: Die Größe des Arrays wird durch die Methode secureCapacity gesteuert . Die Größe erhöht sich um das 1,5-fache . Es wird ein neues Array erstellt und die Elemente werden dorthin verschoben. Wenn wir die Größe auf 10 setzen, dann gilt für das 11. Element:
public List getAllNames() { List names; if (/*необходимые условия выполнены*/) { names = new ArrayList (); /*заполнение списка*/ } return names; }
List names = null; List names = new ArrayList (); List names = new ArrayList (0); List names = new ArrayList (size);
public List getTopNames (int n) { List names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList (n); /*заполнение списка*/ } return names; }
names = new ArrayList ();

/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; } public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
  • Größe ändert sich zu 10 * 3 / 2 + 1 = 16
  • nächste Erhöhung = 16 * 3 / 2 + 1 = 25
  • nächste Erhöhung = 25 * 3 / 2 + 1 = 39 und so weiter.
Bei 100 Elementen muss die JVM mehrmals ein neues Array erstellen und die Elemente hinein kopieren. Unter Berücksichtigung dessen ist es bei Annahmen über die erforderliche Größe des Arrays besser, die Anfangskapazität nahe daran festzulegen. Hier einige Handlungsrichtlinien:
  1. Erstellen Sie eine Sammlung nur, wenn Sie sie benötigen . Andernfalls initialisieren Sie sie auf Null oder verwenden Sie Collections.EMPTY_LIST .
  2. Wenn Sie die genaue erforderliche Größe kennen , geben Sie sie im Sammlungskonstruktor an.
  3. Wenn Sie sicher sind, dass die Anzahl der Elemente 10 nicht überschreitet , können Sie gerne den Standardkonstruktor verwenden.
  4. Das mit der Erstellung einer Sammlung mit Nullgröße verbundene Risiko besteht darin, dass die Häufigkeit der Erstellung neuer Arrays und des Kopierens von Daten höher sein kann. Sie müssen sehr sorgfältig darüber nachdenken, ob der Nutzen der Verwendung von Sammlungen mit Nullgröße wirklich so groß ist .
  5. Wenn Sie zu Beginn der Methode eine zu große Sammlung initialisiert haben und diese verkleinern möchten, gibt es die Methode trimToSize() .
Natürlich gelten diese Richtlinien für die Arbeit mit Array-basierten Sammlungen, und im Fall einer verknüpften Liste macht das alles keinen Sinn. Tatsächlich ist es unwahrscheinlich, dass diese Probleme das Programm zerstören, aber wenn es eine Möglichkeit gibt, es etwas besser zu machen, warum nicht sie nutzen? Habt ihr noch weitere hilfreiche Tipps? Haben Sie Möglichkeiten gefunden, die Dinge besser zu machen? Oder ist das alles unnötig? Was denken Sie?
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION