Comment convertir la liste en int [] en Java?
Ceci est similaire à cette question: Comment convertir int [] en Entier [] en Java?
Je suis nouveau sur Java. Comment puis-je convertir un List<Integer>
à 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 y a une meilleure façon de le faire.
17 answers
Malheureusement, je ne crois 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 deInteger
enint
- Vous ne pouvez pas utiliser
int
comme argument de type pour les génériques, donc aurait pour être une méthode spécifique àint
(ou une méthode qui utilisait la réflexion pour faire une supercherie méchante).
Je crois qu'il y a 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'il y a un modèle qui est copié pour chaque type). C'est moche, mais c'est comme ça que je crains : (
Même si le Arrays
la classe est sortie avant l'arrivée des génériques en Java, elle devrait toujours inclure toutes les surcharges horribles si elle était introduite aujourd'hui (en supposant que vous souhaitiez utiliser des tableaux primitifs).
Personne n'a encore mentionné les flux ajoutés dans Java 8, alors voilà:
int[] array = list.stream().mapToInt(i->i).toArray();
Processus de Pensée:
- simple
Stream#toArray
renvoieObject[]
, 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ériqueA
ne peut pas représenter le primitifint
- ce serait donc bien d'avoir un flux qui pourrait gérer le type primitif
int
, car sa méthodetoArray
retournera probablement aussiint[]
array (renvoyant autre chose commeObject[]
ou même boxedInteger[]
ne serait pas naturel ici). Et heureusement Java 8 a un tel flux:IntStream
-
Alors maintenant, la seule chose que nous devons comprendre est de savoir comment convertir notre
Stream<Integer>
(qui sera renvoyé delist.stream()
) en ceIntStream
brillant. IcimapToInt
la méthode vient à la rescousse. Tout ce que nous devons faire est de fournir un mappage deInteger
àint
. Nous pourrions utiliser quelque chose commeInteger#getValue
qui retourneint
: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, puisque le compilateur sait que le résultat de ce lambda doit être
int
(lambda dansmapToInt
est l'implémentation de l'interfaceToIntFunction
qui attend le corps de la méthodeint applyAsInt(T value)
qui devrait renvoyerint
).Donc nous pouvons simplement écrire
mapToInt((Integer i)->i)
Ou plus simple (puisque le type
Integer i
peut être déduit par le compilateur carList<Integer>#stream()
renvoieStream<Integer>
)mapToInt(i -> i)
En plus de Communes Lang, vous pouvez le faire avec Goyave's méthode Ints.toArray(Collection<Integer> collection)
:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
Cela vous évite d'avoir à effectuer vous-même la conversion de tableau intermédiaire requise par l'équivalent Commons Lang.
La façon la plus simple de le faire est d'utiliser Apache Commons Lang. Il a une classe ArrayUtils pratique qui peut faire ce que vous voulez. Utilisez le toPrimitive
méthode avec la surcharge pour un tableau de Integer
s.
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 entière de la bonne taille. Vous pouvez également utiliser un tableau entier statique de longueur 0 et laisser Java allouer un tableau de droite taille:
static final Integer[] NO_INTS = new Integer[0];
....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
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 (car une liste n'est pas nécessairement une ArrayList, mais pourrait être une liste chaînée, pour laquelle l'accès aléatoire est coûteux)
Java 8 nous a donné un moyen facile de le faire via des flux...
En utilisant la fonction collections stream()
, puis en mappant à ints, vous obtiendrez un IntStream. Avec le IntStream
nous pouvons appeler toArray() ce qui nous donne int []
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
Voici Java 8 code simple ligne pour ce
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
Je vais en jeter un de plus ici. J'ai remarqué plusieurs utilisations de for loops, mais vous n'avez même pas besoin de quoi que ce soit à l'intérieur de la boucle. Je le mentionne uniquement parce que la question d'origine essayait de trouver du code moins verbeux.
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 autorisait plusieurs déclarations dans une boucle for comme le fait C++, nous pourrions aller plus loin et faire for(int i = 0, Itérateur...
À la fin cependant (cette partie est juste mon opinion), si vous allez avoir une fonction ou une méthode d'aide pour faire quelque chose pour vous, il suffit de le mettre en place et l'oublier. Cela peut être un one-liner ou dix; si vous ne le regardez plus jamais, vous ne saurez pas la différence.
Cette boucle simple 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);
}
Si vous mappez simplement un Integer
à un int
alors vous devriez considérer 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();
Soyez juste 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 l'être si vous avez suffisamment de données et de cœurs de processeur. Bien que les opérations d'agrégation vous permettent d'implémenter plus facilement le parallélisme, il reste votre responsabilité de déterminer si votre application convient au parallélisme.
Il existe deux façons de mapper les entiers à leur forme primitive:
-
Via un
ToIntFunction
.mapToInt(Integer::intValue)
-
Via explicite unboxing avec une expression lambda.
mapToInt(i -> i.intValue())
-
Via un déballage implicite (auto-) avec une 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
:
-
Filtrez les valeurs
null
avant le mappage.int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
-
Mapper les valeurs
null
à une valeur par défaut.int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
-
Poignée
null
à l'intérieur de l'expression lambda.int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
int[] ret = new int[list.size()];
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {
ret[i] = iter.next();
}
return ret;
Il n'y a vraiment aucun moyen de" one-lining " ce que vous essayez de faire car toArray renvoie un Objet [] et vous ne pouvez pas convertir Object [] en int [] ou Integer [] en int []
Essayez aussi de Dollar (cochez cette révision):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
Avec Eclipse Collections, vous pouvez faire ce qui 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 comme MutableList
, vous pouvez faire ce qui 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 committer pour les collections Eclipse
En commençant par java 8 cela peut être facilement réalisé en utilisant Stream API
int[] temp = list.stream().mapToInt(Integer::intValue).toArray();
Si vous souhaitez avoir plus d'informations sur la façon dont ce processus est terminé, id tiens à vous rediriger vers ce lien http://www.techiedelight.com/convert-stream-array-java/#2
Je vous recommande d'utiliserList<?>
l'implémentation squelettique de l'API java collections, cela semble être 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));
}
}
Méfiez-vous des inconvénients de la boxe/unboxing
En utilisant un lambda, vous pouvez le faire (compile 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);
}