Anfangsgröße für die ArrayList

257

Sie können die Anfangsgröße für eine ArrayList festlegen, indem Sie dies tun

ArrayList<Integer> arr=new ArrayList<Integer>(10);

Das kannst du aber nicht

arr.add(5, 10);

weil es eine Ausnahme außerhalb der Grenzen verursacht.

Was nützt es, eine Anfangsgröße festzulegen, wenn Sie nicht auf den von Ihnen zugewiesenen Speicherplatz zugreifen können?

Die Add-Funktion ist so definiert, add(int index, Object element)dass ich nicht zu Index 10 hinzufüge.

Cemre
quelle
52
Tatsächlich ist aus den Dokumenten nicht ersichtlich, dass einer Liste mindestens n Elemente hinzugefügt werden müssen, bevor Sie set/addElement n-1 verwenden können .
Wahrnehmung
5
Wahrnehmung: Ich weiß nicht, ob es offensichtlich ist, aber es ist spezifiziert. JavaDoc muss sorgfältig gelesen werden. Throws: IndexOutOfBoundsException - wenn der Index außerhalb des Bereichs liegt (Index <0 || Index> = Größe ()).
Natix
3
Hm, der Konstruktor sagt "Konstruiert eine leere Liste mit der angegebenen Anfangskapazität." Unter der Vorstellung einer leeren Liste kann es keinen Index 5 geben. Aber ich stimme zu, dass dies auf den ersten Blick möglicherweise nicht sichtbar ist ...
quaylar
12
Ich denke, es ist auch fair zu sagen, dass Sie, wenn Sie ein Array mit einem bestimmten Wert initialisieren, davon ausgehen, dass Indizes verfügbar sind, die niedriger als dieser Wert sind - und dies ist ein ArrayList. Ich persönlich hätte gerne eine Methode, mit der ich eine Größe festlegen kann, bei der ich bestimmte Indizes eingeben kann. Diese Methode scheint besonders abwesend zu sein.
Andrew Wyld
1
Welcher taubköpfige Kopf hat die Kollektionen so gestaltet?! Dies erzwingt redundante Arbeit für die parallele Instanziierung einer Struktur mit Elementen variabler Länge (dh ArrayList <String []>, wobei jedes Array eine andere Länge haben kann). Wenn der Speicher bereits zugewiesen ist, sodass die Liste nach dem Hinzufügen von N Elementen nicht neu zugewiesen werden muss, sollten diese Indizes von Anfang an direkt zugänglich sein. Hat niemand bei Oracle dieses Muster nach C / C ++, C #, Objective C und Swift gelernt?!
patrickjp93

Antworten:

387

Sie verwechseln die Größe der Array-Liste mit ihrer Kapazität:

  • Die Größe ist die Anzahl der Elemente in der Liste.
  • Die Kapazität gibt an, wie viele Elemente die Liste möglicherweise aufnehmen kann, ohne ihre internen Strukturen neu zuzuweisen.

Wenn Sie anrufen new ArrayList<Integer>(10), legen Sie die anfängliche Kapazität der Liste fest , nicht ihre Größe. Mit anderen Worten, wenn die Array-Liste auf diese Weise erstellt wird, beginnt ihr Leben leer.

Eine Möglichkeit, der Array-Liste zehn Elemente hinzuzufügen, ist die Verwendung einer Schleife:

for (int i = 0; i < 10; i++) {
  arr.add(0);
}

Anschließend können Sie Elemente an den Indizes 0..9 ändern.

NPE
quelle
51
+1: Eine kürzere Schleife ist while(arr.size() < 10) arr.add(0);Es kann nützlich sein zu sagen, dass die Größe mindestens sein muss 10. zB so können Sie verwendenarr.set(9, n);
Peter Lawrey
10
+1: Großartige Antwort, ich würde +10 geben, wenn ich könnte. Aus der API ist nicht sofort ersichtlich, warum Sie nicht BEIDE Anfangsgröße und Anfangskapazität in einem einzelnen Konstruktoraufruf festlegen können. Sie müssen die API durchlesen und sagen: "Oh, ich denke, ArrayList hat keine Methode oder keinen Konstruktor, um das zu tun"
Demongolem
@PeterLawrey Ihr Code ist möglicherweise kürzer, enthält jedoch zwei Methodenaufrufe pro Schleifeniteration und nicht nur einen.
Neuralmer
@neuralmer Ich würde erwarten, dass size () und add () inline sind, damit zur Laufzeit kein tatsächlicher Methodenaufruf erfolgt.
Peter Lawrey
109

Wenn Sie eine Liste mit einer vordefinierten Größe wünschen, können Sie auch Folgendes verwenden:

List<Integer> arr = Arrays.asList(new Integer[10]);
Gert Jan Schoneveld
quelle
11
Ein kleiner Nachteil hier, das Ergebnis Listist voller Nullen. Mit Guava können wir tun, Ints.asList(new int[10])was unsere Liste mit 0s initialisiert . Sauberes Muster, danke für das Beispiel.
dimo414
1
Die Fragen beziehen sich auf ArrayList <E>. Sie verwenden List <E>. Niemand hat das beobachtet ??? Außerdem haben sie diese irrelevante Antwort positiv bewertet ! Ich stimme Ihrer Antwort nicht zu, weil ich es nie tue. Einfach ... Gott sei Dank!
Apostolos
3
@Apostolos ArrayListist eine Implementierung der ListSchnittstelle und Arrays.asListgibt eine zurück ArrayList. Ich schlage vor, Sie suchen nach Polymorphismus.
Liam Potter
Dies gibt jedoch eine Liste mit einer festen Größe zurück. Der Versuch, mehr Elemente hinzuzufügen, wirftUnsupportedOperationException
Koray Tugay
47

wenn Sie Collections.fill (list, obj) verwenden möchten; Um die Liste mit einem wiederholten Objekt zu füllen, können Sie alternativ verwenden

ArrayList<Integer> arr=new ArrayList<Integer>(Collections.nCopies(10, 0));

Die Zeile kopiert 10 mal 0 in Ihre ArrayList

Farzan Skt
quelle
20

Die Kapazität eines ArrayListist nicht gleich seiner Größe . Die Größe entspricht der Anzahl der Elemente, die in der ArrayList(und jeder anderen ListImplementierung) enthalten sind.

Die Kapazität ist nur die Länge des zugrunde liegenden Arrays, das zum internen Speichern der Elemente des Arrays verwendet wird ArrayList, und ist immer größer oder gleich der Größe der Liste.

Beim Aufrufen set(index, element)der Liste indexbezieht sich das auf die tatsächliche Anzahl der Listenelemente (= Größe) (die in Ihrem Code Null ist, daher AIOOBEwird die ausgelöst), nicht auf die Array-Länge (= Kapazität) (die ein Implementierungsdetail ist) zum ArrayList).

Die setMethode ist allen ListImplementierungen gemeinsam, z. B. LinkedListdie nicht von einem Array implementiert werden, sondern als verknüpfte Kette von Einträgen.

Bearbeiten : Sie verwenden die add(index, element)Methode tatsächlich nicht set(index, element), aber das Prinzip ist hier das gleiche.

Natix
quelle
10

Wenn Sie die Elemente mit Index hinzufügen möchten, können Sie stattdessen ein Array verwenden.

    String [] test = new String[length];
    test[0] = "add";
user3692587
quelle
5
OP wollte zunächst eine Liste verwenden ... kein Array.
Stephan
9

10 ist die Anfangskapazität des AL, nicht die Größe (die 0 ist). Sie sollten die anfängliche Kapazität mit einem hohen Wert erwähnen, wenn Sie viele Elemente haben möchten, da dadurch der Aufwand für die Erweiterung der Kapazität beim Hinzufügen von Elementen vermieden wird.

Bhesh Gurung
quelle
6

Ich denke, eine genaue Antwort auf Ihre Frage wäre:

Durch Festlegen einer Anfangsgröße in einer ArrayList wird die Anzahl reduziert. Oft muss eine Neuzuweisung des internen Speichers erfolgen. Die Liste wird von einem Array unterstützt. Wenn Sie dh die Anfangskapazität 0 angeben, muss die Größe des internen Arrays bereits beim ersten Einfügen eines Elements geändert werden. Wenn Sie eine ungefähre Vorstellung davon haben, wie viele Elemente Ihre Liste enthalten würde, würde das Festlegen der Anfangskapazität die Anzahl verringern. von Speicher-Neuzuweisungen, die während der Verwendung der Liste stattfinden.

Kailar
quelle
3

Dies könnte jemandem helfen -

ArrayList<Integer> integerArrayList = new ArrayList<>(Arrays.asList(new Integer[10]));
Hrishikesh Kadam
quelle
3

Da ich zu spät komme, aber nach Java 8 finde ich diesen folgenden Ansatz mit der StreamAPI persönlicher und kann eine Alternative zur akzeptierten Antwort sein .

Beispielsweise,

Arrays.stream(new int[size]).boxed().collect(Collectors.toList())

Wo sizeist die gewünschte ListGröße und ohne den hier erwähnten Nachteil werden alle Elemente in der Listals initialisiert 0.

(Ich habe eine schnelle Suche durchgeführt und streamkeine Antworten gefunden. Sie können mich gerne informieren, wenn diese Antwort überflüssig ist und ich sie entfernen kann.)

HT Koo
quelle
1

Derzeit enthält Ihre Liste keine Elemente, sodass Sie sie nicht zu Index 5 der Liste hinzufügen können, wenn sie nicht vorhanden ist. Sie verwechseln die Kapazität der Liste mit der aktuellen Größe.

Ruf einfach an:

arr.add(10)

um die Ganzzahl zu Ihrer ArrayList hinzuzufügen

Hunter McMillen
quelle
1

Obwohl Ihre Arrayliste eine Kapazität von 10 hat, enthält die reale Liste hier keine Elemente. Die Methode add wird verwendet, um ein Element in die reale Liste einzufügen. Da es keine Elemente enthält, können Sie kein Element in den Index 5 einfügen.

roll1987
quelle
1

Wenn Sie Ihrem Artikel 10 Elemente hinzufügen möchten, können ArrayListSie Folgendes versuchen:

for (int i = 0; i < 10; i++)
    arr.add(i);

Wenn Sie bereits eine Variable für die Arraygröße deklariert haben, verwenden Sie die Variable sizeanstelle der Zahl '10'.

Panther
quelle
1

Ich hatte mit einem ähnlichen Problem zu kämpfen, und da ich nur weiß, dass die ArrayList eine Array-Implementierung mit veränderbarer Größe der List-Schnittstelle ist, erwarte ich auch, dass Sie jedem Punkt ein Element hinzufügen können, aber zumindest die Option haben, die Anfangsgröße zu definieren. Wie auch immer, Sie können zuerst ein Array erstellen und dieses in eine Liste wie folgt konvertieren:

  int index = 5;
  int size = 10;

  Integer[] array = new Integer[size];
  array[index] = value;
  ...
  List<Integer> list = Arrays.asList(array);

oder

  List<Integer> list = Arrays.asList(new Integer[size]);
  list.set(index, value);
unk
quelle
0

ArrayList myList = new ArrayList (10);

//  myList.add(3, "DDD");
//  myList.add(9, "III");
    myList.add(0, "AAA");
    myList.add(1, "BBB");

    for(String item:myList){
        System.out.println("inside list : "+item);
    }

/ * Erklären Sie, dass die anfängliche Kapazität von Arraylist nichts anderes ist, als intern Schaltzeit zu sparen. Wenn wir das Element intern hinzufügen, wird die Kapazität überprüft, um die Kapazität zu erhöhen. Sie können das Element zunächst mit dem Index 0, dann mit 1 und so weiter hinzufügen. * /

Sambhu
quelle
0

Meine zwei Cent weiter Stream. Ich denke, es ist besser zu verwenden

IntStream.generate(i -> MyClass.contruct())
         .limit(INT_SIZE)
         .collect(Collectors.toList());

mit der Flexibilität, Anfangswerte zu setzen.

anchor2150
quelle