Comment convertir liste en int [] en Java?
c'est similaire à cette question: comment convertir int[] en entier[] en Java?
Je suis nouveau à Java. Comment convertir un List<Integer>
en int[]
en Java? Je suis confus parce que List.toArray()
retourne en fait un Object[]
, qui peut être moulé en 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 faire ce.
17 réponses
malheureusement, je ne crois pas qu'il y ait vraiment est une meilleure façon de le faire en raison de la nature de la manipulation de Java des types primitifs, boxe, tableaux et génériques. En particulier:
-
List<T>.toArray
ne fonctionnera pas parce qu'il n'y a pas de conversion deInteger
enint
- vous ne pouvez pas utiliser
int
comme un argument de type pour les génériques, de sorte qu'il serait avoir d'être unint
- méthode spécifique (ou une qui utilise la réflexion pour faire une vilaine supercherie).
je crois qu'il y a des bibliothèques qui ont des versions autogénérées de ce genre de méthode pour tous les types primitifs (i.e. il y a un modèle qui est copié pour chaque type). C'est laid, mais c'est comme ça j'ai peur: (
bien que la classe Arrays
soit sortie avant l'arrivée des génériques en Java, elle aurait quand même pour inclure toutes les surcharges horribles si elle a été introduite aujourd'hui (en supposant que vous voulez utiliser des tableaux primitifs).
personne n'a encore mentionné les flux ajoutés en Java 8 alors voici:
int[] array = list.stream().mapToInt(i->i).toArray();
processus de pensée:
- simple
Stream#toArray
retourneObject[]
, donc ce n'est pas ce que nous voulons. AussiStream#toArray(IntFunction<A[]> generator)
ne fait pas ce que nous voulons parce que le type génériqueA
ne peut pas représenter primitifint
- donc ce serait bien d'avoir un cours d'eau qui pourrait supporter les primitifs tapez
int
, parce que sa méthodetoArray
retournera très probablement aussiint[]
tableau (retourner quelque chose d'autre commeObject[]
ou même encadréInteger[]
serait contre nature ici). Et heureusement Java 8 a un tel flux:IntStream
-
donc maintenant, la seule chose que nous devons comprendre est comment convertir notre
Stream<Integer>
(qui sera retourné delist.stream()
) à ce brillantIntStream
. Ici, la méthodemapToInt
vient à la rescousse. Tout ce que nous avons à faire est de fournir une certaine correspondance deInteger
àint
. Nous pourrions utiliser quelque chose commeInteger#getValue
qui renvoieint
: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 Unbox, puisque le compilateur sait que le résultat de cette lambda doit être
int
(lambda dansmapToInt
est la mise en œuvre deToIntFunction
interface qui attend le corps pourint applyAsInt(T value)
méthode qui devrait retournerint
).donc nous pouvons simplement écrire
mapToInt((Integer i)->i)
ou plus simple (puisque le type
Integer i
peut être déduit par le compilateur parce queList<Integer>#stream()
retourneStream<Integer>
)mapToInt(i -> i)
en plus de Commons Lang, vous pouvez le faire avec Guava ' s méthode Ints.toArray(Collection<Integer> collection)
:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
cela vous évite d'avoir à faire la conversion de tableau intermédiaire que L'équivalent Lang de Commons exige vous-même.
la façon la plus facile de faire ceci est de faire usage de 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()]));
comme ça, on ne réinvente pas la roue. Commons Lang a un grand nombre de choses utiles que Java a omis. Ci-dessus, j'ai choisi de créer une liste entière de la bonne taille. Vous pouvez également utiliser un 0-longueur statique tableau d'Entiers 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));
int[] toIntArray(List<Integer> list) {
int[] ret = new int[list.size()];
int i = 0;
for (Integer e : list)
ret[i++] = e;
return ret;
}
léger changement à votre code pour éviter l'indexation coûteuse d'une liste (puisqu'une liste n'est pas nécessairement un tableau, mais pourrait être une liste lié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()
et ensuite la cartographie à l'envers, vous obtiendrez un IntStream. Avec le IntStream
nous pouvons appeler toArray () qui nous donne int []
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
Ici est Java 8 une seule ligne de code de 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 pour les boucles, mais vous n'avez même pas besoin de quoi que ce soit à l'intérieur de la boucle. Je n'en parle que parce que la question initiale était de trouver moins de code 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 permettait plusieurs déclarations dans une boucle for comme le fait C++, nous pourrions aller plus loin et faire pour(int i = 0, Iterator it...
à la fin cependant (cette partie est juste mon opinion), si vous allez avoir une fonction d'aide ou une méthode pour faire quelque chose pour vous, il suffit de le configurer et de l'oublier. Il peut s'agir d'une doublure ou d'une doublure; si vous ne la regardez plus, vous ne verrez 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);
}
si vous faites simplement la cartographie d'un Integer
à un int
alors vous devriez considérer en utilisant le parallélisme , puisque votre logique de cartographie ne repose sur Aucune variable en dehors de son champ d'application.
int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();
Juste être conscient de cette
notez que le parallélisme n'est pas automatiquement plus rapide que d'effectuer des opérations en série, bien qu'il puisse l'être si vous avez suffisamment de données et de noyaux de processeur. Alors les opérations d'agrégation vous permettent d'implémenter plus facilement le parallélisme, il est toujours de votre responsabilité de déterminer si votre application est adaptée au parallélisme.
il y a deux façons de cartographier des entiers à leur forme primitive:
-
Via un
ToIntFunction
.mapToInt(Integer::intValue)
-
Via explicit Unbox avec l'expression lambda.
mapToInt(i -> i.intValue())
-
Via implicite (auto -) unboxing with lambda expression.
mapToInt(i -> i)
donné une liste avec une null
valeur
List<Integer> list = Arrays.asList(1, 2, null, 4, 5);
Voici trois options pour gérer null
:
-
filtrer les valeurs
null
avant la cartographie.int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
-
mappez 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 parce que toArray renvoie un objet [] et vous ne pouvez pas lancer d'objet [] vers int [] ou Integer [] vers int []
essayez aussi 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 du 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à une Eclipse Type de Collections 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);
Note: je suis un committer pour Eclipse Collections
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 voulez 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'utiliser List<?>
implémentation squelettique à partir de l'API java collections, il 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 de boxing/unboxing inconvénients
en utilisant un lambda vous pouvez le faire (compilé 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);
}