Java IndexOutOfBoundsException «La source ne tient pas dans la destination»

1. Vue d'ensemble

En Java, faire une copie d'une liste peut parfois produire une IndexOutOfBoundsException: «La source ne rentre pas dans dest». Dans ce court didacticiel, nous allons voir pourquoi nous obtenons cette erreur lors de l'utilisation de la méthode Collections.copy et comment elle peut être résolue. Nous examinerons également des alternatives à Collections.copy pour faire une copie de la liste.

2. Reproduire le problème

Commençons par une méthode pour créer une copie d'une liste à l'aide de la méthode Collections.copy :

static List copyList(List source) { List destination = new ArrayList(source.size()); Collections.copy(destination, source); return destination; }

Ici, la méthode copyList crée une nouvelle liste avec une capacité initiale égale à la taille de la liste source. Ensuite, il essaie de copier les éléments de la liste source dans la liste de destination:

List source = Arrays.asList(1, 2, 3, 4, 5); List copy = copyList(source);

Cependant, une fois que nous appelons la méthode copyList , elle lève une exception java.lang.IndexOutOfBoundsException: Source ne rentre pas dans dest .

3. Cause de l' exception

Essayons de comprendre ce qui n'a pas fonctionné. Selon la documentation de la méthode Collections.copy :

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

Dans notre exemple, nous avons créé une nouvelle liste à l' aide d'un constructeur avec une capacité initiale égale à la taille de la liste source. Il alloue simplement assez de mémoire et ne définit pas réellement les éléments. La taille de la nouvelle liste reste nulle car la capacité et la taille sont des attributs différents de la liste .

Par conséquent, lorsque la méthode Collections.copy essaie de copier la liste source dans la liste de destination, elle lève java.lang.IndexOutOfBoundsException.

4. Solutions

4.1. Collections.copy

Regardons un exemple de travail pour copier une liste dans une autre liste , en utilisant la méthode Collections.copy :

List destination = Arrays.asList(1, 2, 3, 4, 5); List source = Arrays.asList(11, 22, 33); Collections.copy(destination, source);

Dans ce cas, nous copions les trois éléments de la liste source dans la liste de destination. La méthode Arrays.asList initialise la liste avec des éléments et pas seulement une taille, par conséquent, nous pouvons copier la liste source dans la liste de destination avec succès.

Si nous échangeons simplement les arguments de la méthode Collections.copy , cela lèvera java.lang.IndexOutOfBoundsException car la taille de la liste source est inférieure à la taille de la liste de destination .

Après cette opération de copie, la liste de destination ressemble à:

[11, 22, 33, 4, 5]

Outre la méthode Collections.copy , il existe d'autres moyens en Java de créer une copie de List . Jetons un coup d'œil à certains d'entre eux.

4.2. Constructeur ArrayList

L'approche la plus simple pour copier une liste consiste à utiliser un constructeur qui prend un paramètre Collection :

List source = Arrays.asList(11, 22, 33); List destination = new ArrayList(source);

Ici, nous passons simplement la liste source au constructeur de la liste de destination, ce qui crée une copie superficielle de la liste source.

La liste de destination sera juste une autre référence au même objet référencé par la liste source. Ainsi, chaque modification apportée par une référence affectera le même objet.

Par conséquent, l'utilisation d'un constructeur est une bonne option pour copier des objets immuables tels que des entiers et des chaînes.

4.3. tout ajouter

Un autre moyen simple consiste à utiliser la méthode addAll de List :

List destination = new ArrayList(); destination.addAll(source);

La méthode addAll copiera tous les éléments de la liste source dans la liste de destination.

Il y a quelques points à noter concernant cette approche:

  1. Il crée une copie superficielle de la liste source.
  2. Les éléments de la liste source sont ajoutés à la liste de destination.

4.4. Java 8 Streams

Java 8 a introduit l'API Stream, qui est un excellent outil pour travailler avec les collections Java .

En utilisant la méthode stream () , nous faisons une copie de la liste à l'aide de l'API Stream :

List copy = source.stream() .collect(Collectors.toList());

4.5. Java 10

La copie d'une liste est encore plus simple en Java 10. L'utilisation de la méthode copyOf () nous permet de créer une liste immuable contenant les éléments de la collection donnée :

List destination = List.copyOf(sourceList);

Si nous voulons utiliser cette approche, nous devons nous assurer que la liste d' entrée n'est pas nulle et qu'elle ne contient aucun élément nul .

5. Conclusion

Dans cet article, nous avons examiné comment et pourquoi la méthode Collections.copy lève IndexOutOfBoundException «La source ne classe pas dans dest» . Parallèlement, nous avons également exploré différentes façons de copier une liste dans une autre liste.

Les exemples pré-Java-10 et les exemples Java 10 peuvent être trouvés sur GitHub.