80 votes

java.lang.IndexOutOfBoundsException : La source ne rentre pas dans le dest

Sur le code suivant :

static void findSubsets (ArrayList<Integer> numbers, int amount, int index)
{
    ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers.size());
    Collections.copy(numbersCopy, numbers);
}

Je reçois l'erreur :

Exception in thread "main" java.lang.IndexOutOfBoundsException: Source does not fit in dest
        at java.util.Collections.copy(Collections.java:548)
        at backtracking2.Main.findSubsets(Main.java:61)

Pourquoi ?

99voto

pickypg Points 8948

La capacité n'est pas synonyme de taille. Le paramètre de taille que vous transmettez alloue simplement suffisamment de mémoire pour la taille. Il ne définit pas réellement les éléments. C'est en fait une exigence un peu stupide de Collections.copy mais c'en est une quand même.

La partie essentielle de la Collections.copy JavaDocs :

La liste de destination doit être au moins aussi longue que la liste source. Si elle est plus longue, les éléments restants de la liste de destination ne sont pas affectés.

Vous devriez simplement passer le List à la ArrayList pour copier tous les éléments List pour éviter le problème.

10 votes

J'ai dévalorisé ce point, car l'ajouter au constructeur fera une [b]copie superficielle[/b] et ne sera pas la même chose qu'une copie profonde. Manipuler les éléments dans la liste originale, les manipulera également dans la liste 'copiée vers'.

7 votes

Votre remarque est incorrecte. Voir le code source pour ArrayList où une copie profonde de la liste se fait via un appel à toArray et Arrays.copyOf . Les modifications apportées à l'une ou l'autre liste après numbersCopy = new ArrayList<Integer>(numbers) fait pas l'autre. Cela irait certainement à l'encontre de l'objectif du constructeur (et il prend une valeur de Collection et non un List de toute façon).

2 votes

@Boy A moins que tu ne veuilles en venir au fait que le les éléments eux-mêmes ne sont pas également reconstruits pour une copie profonde et fidèle ? Puisque Java n'exige pas de constructeurs de copie, ce serait une exigence presque impossible à satisfaire et une exigence que l'on ne peut pas respecter. Collections.copy ne réalise pas non plus .

30voto

paxdiablo Points 341644

C'est une très bonne question et cela a certainement à voir avec le fait que la définition d'une capacité de collecte n'alloue pas nécessairement les objets sous-jacents, mais pourquoi le faire de cette manière alors que vous pouvez simplement.. :

ArrayList <Integer> numbersCopy = new ArrayList<Integer>(numbers);

13 votes

Il copie la référence

0 votes

@temirbek, non, il ne le fera pas. Je viens de le tester avec le code source ( hg.openjdk.java.net/jdk7/modules/jdk/file/a37326fa7f95/src/ ) dit Arrays.copyOf() signifie qu'il s'agira d'une copie non référencée

0 votes

@Snedden27 : oui, superficiel, mais cela n'a pas d'importance dans ce cas car Integer est immuable.

6voto

Yanick Rochon Points 18537

Le constructeur ArrayList(Collection<? extends E> c) copiera tous les éléments de c dans l'instance nouvellement créée, copiant ainsi numbers en numbersCopy . C'est la même chose que numbersCopy.addAll(numbers) également, ce qui est vraiment ce dont vous avez besoin.

Il est logique que Collection.copy exige que le dest pour qu'il soit suffisamment grand pour contenir tous les éléments de la matrice source array. Une analogie similaire est la fonction C memcpy et autres.

1voto

Arun Nair Points 19

Lors de la création d'un ArrayList pour copier un autre ArrayList en utilisant Collections.copy() nous devons nous assurer que la destination List contient le même nombre de valeurs (pas seulement la même taille) que la source List . Par exemple, si la source ArrayList a les valeurs [Rouge,Bleu,Vert], alors la destination ArrayList devrait également contenir le même nombre d'éléments comme [Orange, Jaune, Bleu]. ArrayList de la même taille que la source ArrayList il donnera OutOfBounds exception.

1voto

Vijay Points 464

Vous pouvez également utiliser, Collections.addAll comme Supposons que nous ayons besoin de copier List1 vers List2, alors List2.addAll(List1); Ici, les fichiers seront ajoutés, si vous voulez que ce soit plus efficace, assurez-vous que vous effacez la liste 2 avant d'ajouter les éléments de la liste 1, comme ceci, list2.clear();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X