web-dev-qa-db-fra.com

Comment convertir la liste <Integer> en int [] en Java?

Ceci est similaire à cette question: Comment convertir int [] en Integer [] en Java?

Je suis nouveau sur Java. Comment puis-je convertir un List<Integer> en int[] en Java? Je suis confus parce que List.toArray() renvoie en fait un Object[], qui peut être converti en nether Integer[] ou int[].

En ce moment, j'utilise une boucle pour le faire:

int[] toIntArray(List<Integer> list){
  int[] ret = new int[list.size()];
  for(int i = 0;i < ret.length;i++)
    ret[i] = list.get(i);
  return ret;
}

Je suis sûr qu'il existe un meilleur moyen de le faire.

528
unknown

Malheureusement, je ne pense pas qu'il y ait vraiment une meilleure façon de le faire en raison de la nature de la gestion par Java des types primitifs, de la boxe, des tableaux et des génériques. En particulier:

  • List<T>.toArray ne fonctionnera pas car il n'y a pas de conversion de Integer à int
  • Vous ne pouvez pas utiliser int en tant qu'argument de type pour les génériques. Par conséquent, doit être une méthode spécifique à int (ou une méthode utilisant la réflexion pour effectuer de superbes ruses).

Je pense qu’il existe des bibliothèques qui ont des versions générées automatiquement de ce type de méthode pour tous les types primitifs (c’est-à-dire qu’un modèle est copié pour chaque type). C'est moche, mais c'est comme ça, j'ai peur :(

Même si la classe Arrays est apparue avant que les génériques n'arrivent en Java, elle devrait néanmoins inclure toutes les surcharges horribles si elle était introduite aujourd'hui (en supposant que vous utilisiez des tableaux primitifs).

202
Jon Skeet

Personne n'a encore mentionné les flux ajoutés dans Java 8, alors voici:

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

Processus de pensée:

  • simple Stream#toArray renvoie Object[], donc ce n'est pas ce que nous voulons. De plus, Stream#toArray(IntFunction<A[]> generator) ne fait pas ce que nous voulons car le type générique A ne peut pas représenter la primitive int
  • il serait donc agréable d’avoir un flux capable de gérer le type primitif int au lieu du wrapper Integer, car sa méthode toArray renverra très probablement également le tableau int[] (renvoyant quelque chose d’autre comme Object[] ou même boxed Integer[] ne serait pas naturel ici). Et heureusement Java 8 a un tel flux qui est IntStream
  • il ne reste donc maintenant plus qu’à comprendre comment convertir notre Stream<Integer> (qui sera renvoyé de list.stream()) en cet brillant IntStream. Ici Stream#mapToInt(ToIntFunction<? super T> mapper) la méthode vient à la rescousse. Tout ce que nous avons à faire est de lui passer le mappage de Integer à int. Nous pourrions utiliser quelque chose comme Integer#getValue qui renvoie int comme:

    mapToInt( (Integer i) -> i.intValue() )  
    

    (ou si quelqu'un préfère mapToInt(Integer::intValue))

    mais un code similaire peut être généré en utilisant unboxing, car le compilateur sait que le résultat de ce lambda doit être int (lambda dans mapToInt est une implémentation de l'interface ToIntFunction qui attend un corps pour la méthode int applyAsInt(T value) qui doit renvoyer int).

    Donc, nous pouvons simplement écrire

    mapToInt((Integer i)->i)
    

    De plus, puisque Integer saisissez (Integer i) peut être déduit par le compilateur, car List<Integer>#stream() renvoie Stream<Integer>, nous pouvons également le sauter, ce qui nous laisse avec

    mapToInt(i -> i)
    
516
Pshemo

En plus de Commons Lang, vous pouvez le faire avec la méthode de GuavaInts.toArray(Collection<Integer> collection) :

List<Integer> list = ...
int[] ints = Ints.toArray(list);

Cela vous évite d'avoir à effectuer la conversion de matrice intermédiaire que l'équivalent de Commons Lang vous demande.

194
ColinD

Le moyen le plus simple de procéder consiste à utiliser Apache Commons Lang . Il a une classe pratique ArrayUtils qui peut faire ce que vous voulez. Utilisez la méthode toPrimitive avec la surcharge pour un tableau de Integers.

List<Integer> myList;
 ... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));

De cette façon, vous ne réinventez pas la roue. Commons Lang a beaucoup de choses utiles que Java a laissées de côté. Ci-dessus, j'ai choisi de créer une liste Integer de la bonne taille. Vous pouvez également utiliser un tableau Integer statique de longueur 0 et laisser Java allouer un tableau de la bonne taille:

static final Integer[] NO_INTS = new Integer[0];
   ....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
168
Eddie

Java 8 nous a fourni un moyen simple de le faire via des flux ...

En utilisant la fonction collections stream() puis en effectuant un mappage sur ints, vous obtiendrez un flux IntStream. Avec le IntStream nous pouvons appeler toArray (), ce qui nous donne int []

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

to int []

à IntStream

52
Pumphouse
int[] toIntArray(List<Integer> list)  {
    int[] ret = new int[list.size()];
    int i = 0;
    for (Integer e : list)  
        ret[i++] = e;
    return ret;
}

Légère modification de votre code pour éviter une indexation de liste coûteuse (puisqu'un liste n'est pas nécessairement une liste de tableaux, mais peut être une liste chaînée, pour laquelle l'accès aléatoire coûte cher)

50
Mike

Voici Java 8 code à ligne unique pour cela

public int[] toIntArray(List<Integer> intList){
       return intList.stream().mapToInt(Integer::intValue).toArray();
}
12
Noor Nawaz

Si vous mappez simplement un Integer à un int, vous devriez alors envisager en utilisant le parallélisme , car votre logique de mappage ne repose sur aucune variable en dehors de sa portée.

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

Juste être conscient de cela

Notez que le parallélisme n’est pas automatiquement plus rapide que d’effectuer des opérations en série, bien que cela puisse être le cas si vous avez suffisamment de données et de cœurs de processeur. Bien que les opérations d'agrégat vous permettent de mettre en œuvre plus facilement le parallélisme, il vous incombe de déterminer si votre application convient au parallélisme.


Il existe deux manières de mapper des entiers à leur forme primitive:

  1. Via un ToIntFunction.

    mapToInt(Integer::intValue)
    
  2. Via explicite nboxing avec expression lambda.

    mapToInt(i -> i.intValue())
    
  3. Via un (automatiques) unboxing implicite avec expression lambda.

    mapToInt(i -> i)
    

Étant donné une liste avec une valeur null

List<Integer> list = Arrays.asList(1, 2, null, 4, 5);

Voici trois options pour gérer null:

  1. Filtrez les valeurs null avant le mappage.

    int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
    
  2. Mappez les valeurs null sur une valeur par défaut.

    int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
    
  3. Poignée null à l'intérieur de l'expression lambda.

    int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
    
7
Mr. Polywhirl

Je vais en lancer un autre ici. J'ai remarqué plusieurs utilisations de boucles for, mais vous n'avez même besoin de rien à l'intérieur de la boucle. Je mentionne cela uniquement parce que la question initiale cherchait à trouver un code moins détaillé.

int[] toArray(List<Integer> list) {
    int[] ret = new int[ list.size() ];
    int i = 0;
    for( Iterator<Integer> it = list.iterator(); 
         it.hasNext(); 
         ret[i++] = it.next() );
    return ret;
}

Si Java permettait plusieurs déclarations dans une boucle for comme C++, nous pourrions aller plus loin et faire pour (int i = 0, Iterator it ...

En fin de compte cependant (cette partie n’est que mon opinion), si vous allez avoir une fonction ou une méthode d’aide pour faire quelque chose pour vous, configurez-le et oubliez-le. Ce peut être un one-line ou dix; si vous ne le regarderez plus jamais, vous ne saurez pas la différence.

7
Loduwijk

Cette simple boucle est toujours correcte! pas de bugs

  int[] integers = new int[myList.size()];
  for (int i = 0; i < integers.length; i++) {
      integers[i] = myList.get(i);
  }
6
THANN Phearum

Il n'y a vraiment aucun moyen de "one-lineing" sur ce que vous essayez de faire car toArray renvoie un objet [] et vous ne pouvez pas transtyper Object [] en int [] ou Integer [] en int [].

5
neesh
int[] ret = new int[list.size()];       
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {       
    ret[i] = iter.next();                
}                                        
return ret;                              
4
gerardw

essayez aussi Dollar ( cocher cette révision ):

import static com.humaorie.dollar.Dollar.*
...

List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
3
dfa

Avec Eclipse Collections , vous pouvez procéder comme suit si vous avez une liste de type Java.util.List<Integer>:

List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = LazyIterate.adapt(integers).collectInt(i -> i).toArray();

Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);

Si vous avez déjà un type de collections Eclipse tel que MutableList , vous pouvez procéder comme suit:

MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = integers.asLazy().collectInt(i -> i).toArray();

Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);

Remarque: je suis un partisan des collections Eclipse

2
Donald Raab

Je vous recommanderais d'utiliser List<?> squelette à partir de l'API Java collections, cela semble très utile dans ce cas particulier:

package mypackage;

import Java.util.AbstractList;
import Java.util.Arrays;
import Java.util.Collections;
import Java.util.List;

public class Test {

//Helper method to convert int arrays into Lists
static List<Integer> intArrayAsList(final int[] a) {
    if(a == null)
        throw new NullPointerException();
    return new AbstractList<Integer>() {

        @Override
        public Integer get(int i) {
            return a[i];//autoboxing
        }
        @Override
        public Integer set(int i, Integer val) {
            final int old = a[i];
            a[i] = val;//auto-unboxing
            return old;//autoboxing
        }
        @Override
        public int size() {
            return a.length;
        }
    };
}

public static void main(final String[] args) {
    int[] a = {1, 2, 3, 4, 5};
    Collections.reverse(intArrayAsList(a));
    System.out.println(Arrays.toString(a));
}
}

Attention aux inconvénients de la boxe et du déballage

1
DennisTemper

En utilisant un lambda, vous pouvez faire ceci (compiler dans jdk lambda):

public static void main(String ars[]) {
        TransformService transformService = (inputs) -> {
            int[] ints = new int[inputs.size()];
            int i = 0;
            for (Integer element : inputs) {
                ints[ i++ ] = element;
            }
            return ints;
        };

        List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };

        int[] results = transformService.transform(inputs);
    }

    public interface TransformService {
        int[] transform(List<Integer> inputs);
    }
0
NimChimpsky