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.
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
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).
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:
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
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)
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.
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 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 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));
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();
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)
Voici Java 8 code à ligne unique pour cela
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
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:
Via un ToIntFunction
.
mapToInt(Integer::intValue)
Via explicite nboxing avec expression lambda.
mapToInt(i -> i.intValue())
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
:
Filtrez les valeurs null
avant le mappage.
int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
Mappez les valeurs null
sur 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();
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.
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);
}
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 [].
int[] ret = new int[list.size()];
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {
ret[i] = iter.next();
}
return ret;
essayez aussi Dollar ( cocher cette révision ):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
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
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
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);
}