web-dev-qa-db-fra.com

Comment convertir une ArrayList contenant des entiers en tableau int primitif?

J'essaie de convertir une ArrayList contenant des objets Integer en primitive int [] avec le code suivant, mais une erreur de compilation a été générée. Est-il possible de convertir en Java?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);
249
Snehal

Vous pouvez convertir, mais je ne pense pas que quoi que ce soit construit pour le faire automatiquement:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    for (int i=0; i < ret.length; i++)
    {
        ret[i] = integers.get(i).intValue();
    }
    return ret;
}

(Notez que cela lève une exception NullPointerException si integers ou l'un de ses éléments est null.)

EDIT: Selon les commentaires, vous pouvez utiliser l'itérateur de liste pour éviter des coûts désagréables avec des listes telles que LinkedList:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    Iterator<Integer> iterator = integers.iterator();
    for (int i = 0; i < ret.length; i++)
    {
        ret[i] = iterator.next().intValue();
    }
    return ret;
}
206
Jon Skeet

Si vous utilisez Java-8 , il existe également un autre moyen de procéder.

int[] arr = list.stream().mapToInt(i -> i).toArray();

Qu'est-ce qu'il fait est:

  • obtenir un Stream<Integer> de la liste
  • obtenir une IntStream en mappant chaque élément sur lui-même (fonction d'identité), déconditionnant la valeur int détenue par chaque objet Integer (effectuée automatiquement depuis Java 5)
  • obtenir le tableau de int en appelant toArray

Vous pouvez également appeler explicitement intValue via une référence de méthode, à savoir:

int[] arr = list.stream().mapToInt(Integer::intValue).toArray();

Il est également intéressant de noter que vous pouvez obtenir une NullPointerException si vous avez une référence null dans la liste. Cela pourrait être facilement évité en ajoutant une condition de filtrage au pipeline de flux comme ceci:

                       //.filter(Objects::nonNull) also works
int[] arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray();

Exemple:

List<Integer> list = Arrays.asList(1, 2, 3, 4);
int[] arr = list.stream().mapToInt(i -> i).toArray(); //[1, 2, 3, 4]

list.set(1, null); //[1, null, 3, 4]
arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray(); //[1, 3, 4]
182
Alexis C.

Apache Commons a une classe ArrayUtils, qui a une méthode toPrimitive () qui fait exactement cela.

import org.Apache.commons.lang.ArrayUtils;
...
    List<Integer> list = new ArrayList<Integer>();
    list.add(new Integer(1));
    list.add(new Integer(2));
    int[] intArray = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));

Cependant, comme Jon l'a montré, il est assez facile de le faire vous-même au lieu d'utiliser des bibliothèques externes.

60
Björn

Google Guava

Google Guava fournit un moyen élégant de le faire en appelant Ints.toArray .

_List<Integer> list = ...;
int[] values = Ints.toArray(list);
_
59
Snehal

Je pense qu'itérer l'utilisation de l'itérateur de la liste est une meilleure idée, car list.get(i) peut avoir de mauvaises performances en fonction de l'implémentation de la liste:

private int[] buildIntArray(List<Integer> integers) {
    int[] ints = new int[integers.size()];
    int i = 0;
    for (Integer n : integers) {
        ints[i++] = n;
    }
    return ints;
}
41
Matthew Willis

utiliser Dollar devrait être assez simple:

List<Integer> list = $(5).toList(); // the list 0, 1, 2, 3, 4  
int[] array = $($(list).toArray()).toIntArray();

Je prévois d'améliorer le DSL afin de supprimer l'appel intermédiaire toArray()

6
dfa

Si vous utilisez Eclipse Collections , vous pouvez utiliser la méthode collectInt() pour passer d'un conteneur d'objet à un conteneur primitive int.

List<Integer> integers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
MutableIntList intList =
  ListAdapter.adapt(integers).collectInt(i -> i);
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, intList.toArray());

Si vous pouvez convertir votre ArrayList en FastList, vous pouvez vous débarrasser de l'adaptateur.

Assert.assertArrayEquals(
  new int[]{1, 2, 3, 4, 5},
  Lists.mutable.with(1, 2, 3, 4, 5)
    .collectInt(i -> i).toArray());

Remarque: Je suis un partisan des collections Eclipse.

3
Craig P. Motlin

Cela me fait oublier que nous encourageons les méthodes personnalisées uniques chaque fois qu'une bibliothèque parfaitement utilisée et bien utilisée comme Apache Commons a déjà résolu le problème. Bien que la solution soit triviale, voire absurde, il est irresponsable d'encourager un tel comportement en raison de sa maintenance et de son accessibilité à long terme.

Il suffit d'aller avec Apache Commons

2
Andrew F.

Vous pouvez simplement le copier dans un tableau:

int[] arr = new int[list.size()];
for(int i = 0; i < list.size(); i++) {
    arr[i] = list.get(i);
}

Pas trop chic; mais, hé, ça marche ...

1
sagiksp

Ce segment de code fonctionne pour moi, essayez ceci:

Integer[] arr = x.toArray(new Integer[x.size()]);

Il convient de mentionner ArrayList devrait être déclaré comme ceci:

ArrayList<Integer> list = new ArrayList<>();
0
user3444748