Taille initiale pour ArrayList

257

Vous pouvez définir la taille initiale d'une liste de tableaux en faisant

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

Cependant, vous ne pouvez pas faire

arr.add(5, 10);

car il provoque une exception hors limites.

À quoi sert de définir une taille initiale si vous ne pouvez pas accéder à l'espace que vous avez alloué?

La fonction d'ajout est définie comme add(int index, Object element)si je n'ajoute pas à l'index 10.

Cemre
la source
52
En fait, il n'est pas évident d'après les documents qu'une liste doit avoir au moins n éléments ajoutés avant de pouvoir l' set/addélément n-1 .
Perception le
5
Perception: je ne sais pas si c'est évident, mais c'est précisé. Il faut lire attentivement JavaDoc. Jetées: IndexOutOfBoundsException - si index hors plage (index <0 || index> = size ()).
Natix
3
Hm, le constructeur dit "Construit une liste vide avec la capacité initiale spécifiée.", En prenant la notion de liste vide, il ne peut pas y avoir d'index 5. Mais je suis d'accord que cela pourrait ne pas être visible à première vue ...
quaylar
12
Je pense qu'il est également juste de dire que si vous initialisez un tableau à une valeur spécifique, vous allez supposer que des indices inférieurs à cette valeur sont disponibles - et c'est un ArrayList. Personnellement, j'aimerais une méthode qui me permettrait de définir une taille telle que je puisse mettre les choses à des indices spécifiques. Cette méthode semble notamment absente.
Andrew Wyld
1
Quel numbskull a conçu les collections de cette façon?! Cela force le travail redondant pour l'instanciation parallèle d'une structure avec des éléments de longueur variable (ie ArrayList <String []> où chaque tableau peut avoir une longueur différente). Si la mémoire est déjà allouée, la liste n'a donc pas besoin d'être réallouée après l'ajout de N éléments, ces indices doivent être directement accessibles depuis le début. Personne chez Oracle n'a appris ce modèle après C / C ++, C #, Objective C et Swift?!
patrickjp93

Réponses:

387

Vous confondez la taille de la liste de baies avec sa capacité:

  • la taille est le nombre d'éléments dans la liste;
  • la capacité est le nombre d'éléments que la liste peut potentiellement contenir sans réaffecter ses structures internes.

Lorsque vous appelez new ArrayList<Integer>(10), vous définissez la capacité initiale de la liste , pas sa taille. En d'autres termes, lorsqu'elle est construite de cette manière, la liste de tableaux commence sa vie vide.

Une façon d'ajouter dix éléments à la liste de tableaux consiste à utiliser une boucle:

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

Cela fait, vous pouvez maintenant modifier les éléments aux indices 0..9.

NPE
la source
51
+1: Une boucle plus courte est while(arr.size() < 10) arr.add(0);Il peut être utile de dire que la taille doit être d'au moins 10. par exemple pour que vous puissiez utiliserarr.set(9, n);
Peter Lawrey
10
+1: Excellente réponse, je donnerais +10 si je le pouvais. Il n'est pas immédiatement évident à partir de l'API pourquoi vous ne pouvez pas définir la taille initiale et la capacité initiale dans un seul appel de constructeur. Vous devez en quelque sorte lire l'API et dire "Oh, je suppose qu'ArrayList n'a pas de méthode ni de constructeur pour le faire"
demongolem
@PeterLawrey Votre code peut être plus court, mais contient deux appels de méthode par itération de boucle, plutôt qu'un seul.
neuralmer
@neuralmer Je m'attendrais à ce que size () et add () soient alignés afin qu'aucun appel de méthode réel ne se produise au moment de l'exécution.
Peter Lawrey
109

Si vous voulez une liste avec une taille prédéfinie, vous pouvez également utiliser:

List<Integer> arr = Arrays.asList(new Integer[10]);
Gert Jan Schoneveld
la source
11
Léger inconvénient ici, le résultat Listest plein de nulls. Avec Guava, nous pouvons faire Ints.asList(new int[10])ce qui initialisera notre liste avec 0s. Modèle propre cependant, merci pour l'exemple.
dimo414
1
La question parle d'ArrayList <E>. Vous utilisez Liste <E>. Personne n'a observé cela ??? De plus, ils ont voté pour cette réponse hors de propos ! Je ne sous-estime pas votre réponse parce que je ne le fais jamais. Simplement ... Godssake!
Apostolos
3
@Apostolos ArrayListest une implémentation de l' Listinterface et Arrays.asListrenvoie un ArrayList. Je vous suggère de rechercher le polymorphisme.
Liam Potter
Cela renvoie cependant une liste avec une taille fixe. Essayer d'ajouter plus de lancers d'élémentsUnsupportedOperationException
Koray Tugay
47

si vous souhaitez utiliser Collections.fill (list, obj); afin de remplir la liste avec un objet répété, vous pouvez également utiliser

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

la ligne copie 10 fois 0 dans votre ArrayList

Farzan Skt
la source
20

La capacité d'un ArrayListn'est pas la même que sa taille . La taille est égale au nombre d'éléments contenus dans ArrayList(et toute autre Listimplémentation).

La capacité est juste la longueur du tableau sous-jacent qui est utilisé pour stocker en interne les éléments de la ArrayList, et est toujours supérieure ou égale à la taille de la liste.

Lors de l'appel set(index, element)sur la liste, le se indexrapporte au nombre réel des éléments de la liste (= taille) (qui est zéro dans votre code, donc le AIOOBEest levé), pas à la longueur du tableau (= capacité) (qui est un détail d'implémentation spécifique au ArrayList).

La setméthode est commune à toutes les Listimplémentations, telles que LinkedList, qui n'est pas réellement implémentée par un tableau, mais comme une chaîne d'entrées liée.

Edit : Vous utilisez en fait la add(index, element)méthode, non set(index, element), mais le principe est le même ici.

Natix
la source
10

Si vous souhaitez ajouter les éléments avec index, vous pouvez utiliser à la place un tableau.

    String [] test = new String[length];
    test[0] = "add";
user3692587
la source
5
OP voulait d'abord utiliser une liste ... pas un tableau.
Stephan
9

10 est la capacité initiale de l'AL, pas la taille (qui est 0). Vous devez mentionner la capacité initiale à une valeur élevée lorsque vous allez avoir beaucoup d'éléments, car cela évite le surcoût d'augmenter la capacité lorsque vous continuez à ajouter des éléments.

Bhesh Gurung
la source
6

Je suppose qu'une réponse exacte à votre question serait:

La définition d'une taille initiale sur une liste de tableaux réduit le nombre. de fois la réallocation de mémoire interne doit se produire. La liste est soutenue par un tableau. Si vous spécifiez par exemple la capacité initiale 0, dès la première insertion d'un élément, le tableau interne devra être redimensionné. Si vous avez une idée approximative du nombre d'éléments que votre liste contiendrait, la définition de la capacité initiale réduirait le nombre. des réallocations de mémoire se produisent pendant que vous utilisez la liste.

quaylar
la source
3

Cela pourrait aider quelqu'un -

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

Étant en retard à cela, mais après Java 8 , je trouve personnellement cette approche suivante avec l' StreamAPI plus concise et peut être une alternative à la réponse acceptée .

Par exemple,

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

sizeest la Listtaille souhaitée et sans l'inconvénient mentionné ici , tous les éléments du Listsont initialisés comme 0.

(J'ai fait une recherche rapide et je n'ai vu streamaucune réponse publiée - n'hésitez pas à me faire savoir si cette réponse est redondante et je peux la supprimer)

HT Koo
la source
1

À l'heure actuelle, il n'y a aucun élément dans votre liste, vous ne pouvez donc pas l'ajouter à l'index 5 de la liste lorsqu'elle n'existe pas. Vous confondez la capacité de la liste avec sa taille actuelle.

Il suffit d'appeler:

arr.add(10)

ajouter l'entier à votre ArrayList

Hunter McMillen
la source
1

Bien que votre arraylist ait une capacité de 10, la vraie liste ne contient aucun élément ici. La méthode add est utilisée pour insérer un élément dans la liste réelle. Comme il ne contient aucun élément, vous ne pouvez pas insérer d'élément dans l'index de 5.

roll1987
la source
1

Si vous souhaitez ajouter 10 éléments à votre, ArrayListvous pouvez essayer cela:

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

Si vous avez déjà déclaré une variable de taille de tableau, vous utiliseriez la variable sizeau lieu du nombre «10»

panthère
la source
1

J'ai fait face à un problème similaire, et sachant simplement que arrayList est une implémentation de tableau redimensionnable de l'interface List, je m'attends également à ce que vous puissiez ajouter un élément à n'importe quel point, mais au moins avoir la possibilité de définir la taille initiale. Quoi qu'il en soit, vous pouvez d'abord créer un tableau et le convertir en une liste comme:

  int index = 5;
  int size = 10;

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

ou

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

ArrayList myList = nouveau 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);
    }

/ * Déclarer la capacité initiale de l'arrayliste n'est rien d'autre que gagner du temps de changement en interne; lorsque nous ajoutons l'élément en interne, il vérifie la capacité pour augmenter la capacité, vous pouvez ajouter l'élément à l'indice 0 initialement, puis 1 et ainsi de suite. * /

sambhu
la source
0

Mes deux cents dessus Stream. Je pense qu'il vaut mieux utiliser

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

avec la flexibilité de mettre toutes les valeurs initiales.

anch2150
la source