Come convertire un ArrayList contenente numeri interi in array int primitivo?


297

Sto cercando di convertire un ArrayList contenente oggetti Integer in int primitivo [] con il seguente pezzo di codice, ma sta generando un errore di tempo di compilazione. È possibile convertire in Java?

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

10
Non un duplicato ESATTO di quella domanda (anche se non molto lontano)
Jonik,

1
Sì, questa è una ArrayList, "duplicato" riguarda una matrice normale.
Scott McIntyre,

3
Se non hai bisogno di ints primitivi, puoi usare: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor il

Risposte:


219

Puoi convertire, ma non credo che ci sia qualcosa incorporato per farlo automaticamente:

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;
}

(Nota che questo genererà una NullPointerException se uno integerso più elementi al suo interno lo sono null.)

MODIFICA: Come da commenti, potresti voler utilizzare l'iteratore di elenchi per evitare costi negativi con elenchi come 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;
}

21
Potrebbe essere meglio iterare usando l'iteratore dell'elenco (con per ciascuno) in modo da evitare hit di performance su elenchi il cui accesso non è O (1).
Matthew Willis,

@Matthew: Sì, possibilmente - lo modificherò in alternativa.
Jon Skeet,

1
Puoi anche utilizzare il fatto che ArrayList implementa Iterable (tramite ereditarietà Collection) e fare: for (int n: intero) {ret [counter ++] = n; } ... e inizializza int counter = 0;
Gardarh,

8
molto più facile ora in Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel,

241

Se stai usando c'è anche un altro modo per farlo.

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

Quello che fa è:

  • ottenere un Stream<Integer>dalla lista
  • ottenere un IntStreammappando ogni elemento su se stesso (funzione di identità), unboxing il intvalore trattenuto da ciascun Integeroggetto (fatto automaticamente da Java 5)
  • ottenere l'array di intchiamandotoArray

È inoltre possibile chiamare esplicitamente intValuetramite un riferimento al metodo, ad esempio:

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

Vale anche la pena ricordare che potresti ottenere un NullPointerExceptionse hai qualche nullriferimento nell'elenco. Ciò potrebbe essere facilmente evitato aggiungendo una condizione di filtro alla pipeline del flusso in questo modo:

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

Esempio:

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]

Vedo che questo può essere usato per i doubletipi; non ci sono equivalenti per i floattipi?
code_dredd,

Ho visto il vantaggio di Java 8 con la tua spiegazione elaborata.
Eugene,

Ed è per questo che l'API Java 8+ Stream è bellissima.
Pranav A.

67

Google Guava

Google Guava fornisce un modo pulito per farlo chiamando Ints.toArray.

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

6
Penso che questa sarà la risposta per me - porterò una libreria su una funzione di copia e incolla ogni giorno .. specialmente una libreria che probabilmente utilizza già un progetto di dimensioni decenti. Spero che questa risposta ottenga più voti e visibilità in futuro.
Sean Connolly,

61

Apache Commons ha una classe ArrayUtils, che ha un metodo toPrimitive () che fa esattamente questo.

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]));

Tuttavia, come ha dimostrato Jon, è abbastanza facile farlo da soli invece di usare librerie esterne.


2
Si noti che questo approccio farà due copie complete della sequenza: un intero [] creato da toArray e uno int [] creato all'interno diPrimitive. L'altra risposta di Jon crea e riempie solo un array. Qualcosa da considerare se si dispone di elenchi di grandi dimensioni e le prestazioni sono importanti.
paraquat,

Ho misurato le prestazioni usando ArrayUtils vs Java puro e su piccoli elenchi (<25 elementi) Java puro è più di 100 volte più veloce. Per gli elementi 3k, il java puro è ancora quasi 2 volte più veloce ... (ArrayList <Integer> -> int [])
Oskar Lund

@paraquat e Oskar Lund che in realtà non sono corretti. Sì, il codice fornito creerà due array, ma questo approccio no. Il problema in questo codice qui è l'uso di un array di lunghezza zero come argomento. Il codice sorgente ArrayList.toArray mostra che se il contenuto si adatta, verrà utilizzato l'array originale. Penso che in un confronto equo troverai questo metodo più efficiente (se non di più) e, ovviamente, meno codice da mantenere.
Sean Connolly,


1
Qual è lo scopo del nuovo numero intero [0]?
Adam Hughes,

41

Credo che iterare usando l'iteratore dell'elenco sia un'idea migliore, poiché list.get(i)può avere scarse prestazioni a seconda dell'implementazione dell'elenco:

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

6

usare Dollar dovrebbe essere abbastanza semplice:

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

Sto pianificando di migliorare il DSL per rimuovere la toArray()chiamata intermedia


1
Ehi, volevo solo dire che non avevo mai visto Dollar prima, ma sto sicuramente provando il mio prossimo progetto. Questa è una piccola api elegante che ci vai, continua così :)
Bart Vandendriessche,

4

Questo funziona bene per me :)

Trovato su https://www.techiedelight.com/convert-list-integer-array-int/

import java.util.Arrays;
import java.util.List;

class ListUtil
{
    // Program to convert list of integer to array of int in Java
    public static void main(String args[])
    {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

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

        System.out.println(Arrays.toString(primitive));
    }
}

3

Mi sorprende che incoraggiamo metodi personalizzati una tantum ogni volta che una libreria perfettamente funzionante e ben usata come Apache Commons ha già risolto il problema. Sebbene la soluzione sia banale se non assurda, è irresponsabile incoraggiare un simile comportamento a causa della manutenzione e dell'accessibilità a lungo termine.

Basta andare con Apache Commons


7
Sono d'accordo con il commentatore precedente. Non solo trascini in Apache Commons, ma si traduce facilmente in una vasta serie di dipendenze transitive che devono anche essere trascinate. Recentemente ho potuto rimuovere un numero incredibile di dipendenze sostituendo una riga di codice :-( Le dipendenze sono costose e scrivere codice di base come questo è una buona pratica
Peter Kriens,

1
Concordato con @PeterKriens. Semmai, l'errore è in Java per non supportare conversioni semplici come questa nei suoi tipi di dati standard
Adam Hughes,

3

Se si utilizzano le raccolte Eclipse , è possibile utilizzare il collectInt()metodo per passare da un contenitore di oggetti a un contenitore int primitivo.

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());

Se riesci a convertire il tuo ArrayListin a FastList, puoi eliminare l'adattatore.

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

Nota: sono un committer per le raccolte Eclipse.


3

Java 8:

int[] intArr = Arrays.stream(integerList).mapToInt(i->i).toArray();

2

Arrays.setAll ()

    List<Integer> x = new ArrayList<>(Arrays.asList(7, 9, 13));
    int[] n = new int[x.size()];
    Arrays.setAll(n, x::get);

    System.out.println("Array of primitive ints: " + Arrays.toString(n));

Produzione:

Matrice di ints primitivi: [7, 9, 13]

Le stesse opere per un array di longo double, ma non per array boolean, char, byte, shorto float. Se hai un elenco davvero enorme, c'è anche un parallelSetAllmetodo che potresti usare invece.

Per me questo è abbastanza buono ed elgante che non vorrei avere una libreria esterna né usare i flussi per esso.

Link alla documentazione: Arrays.setAll(int[], IntUnaryOperator)


1

Puoi semplicemente copiarlo su un array:

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

Non troppo lussuoso; ma, ehi, funziona ...


1

Una soluzione a una riga molto semplice è:

Integer[] i = arrlist.stream().toArray(Integer[]::new);

0

Questo segmento di codice funziona per me, prova questo:

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

Vale la pena ricordare che ArrayList dovrebbe essere dichiarato così:

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

5
Ciao solo un gentile promemoria che OP vuole un array primitivo non un array di oggetti.
OLIVER.KOO

3
Int primitivo non wrapper Integer!
Bartzilla,

-4
   List<Integer> list = new ArrayList<Integer>();

    list.add(1);
    list.add(2);

    int[] result = null;
    StringBuffer strBuffer = new StringBuffer();
    for (Object o : list) {
        strBuffer.append(o);
        result = new int[] { Integer.parseInt(strBuffer.toString()) };
        for (Integer i : result) {
            System.out.println(i);
        }
        strBuffer.delete(0, strBuffer.length());
    }

1
Questa risposta non funziona, restituisce un array con un singolo elemento anziché più elementi.
Mistico

Perché usare StringBuffer? Perché convertire l'Integer in una stringa e quindi in un numero intero e quindi in un int e quindi di nuovo in un numero intero? Perché usare un array con un singolo elemento al suo interno e perché passare sopra quell'array a singolo elemento quando contiene solo un elemento? Perché trasmettere gli Integer agli oggetti nel loop esterno? Ci sono così tante domande qui. @CodeMadness è solo un account troll?
Victor Zamanian,

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

accesso arrcome al solito int[].


5
questo non risponde alla domanda, la domanda riguardava la conversione in tipo primitivo (int)
Asaf,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.