Como converter um ArrayList contendo números inteiros em primitivo int array?

297

Estou tentando converter um ArrayList contendo objetos Inteiros para int primitivo] com o seguinte pedaço de código, mas está lançando um erro de tempo de compilação. É possível converter em Java?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);
Snehal
fonte
10
Não é uma duplicata exata da pergunta (embora não muito longe também)
Jonik
1
Sim, este é um ArrayList, "duplicado" é sobre um array normal.
9788 Scott McIntyre
3
Se você não precisa de ints primitivos, pode usar: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor 10/15/15

Respostas:

219

Você pode converter, mas acho que não há nada incorporado para fazer isso 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;
}

(Observe que isso lançará uma NullPointerException se um integersou qualquer elemento dele for null.)

EDIT: conforme os comentários, convém usar o iterador da lista para evitar custos desagradáveis ​​com listas como 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;
}
Jon Skeet
fonte
21
Talvez seja melhor iterar usando o iterador da Lista (com cada um) para evitar resultados de desempenho em listas cujo acesso não é O (1).
Matthew Willis
@ Matthew: Sim, possivelmente - irá editar para dar isso como uma alternativa.
Jon tiro ao prato
1
Você também pode utilizar o fato de o ArrayList implementar Iterable (via herança de coleção) e fazer: for (int n: número inteiro) {ret [counter ++] = n; } ... e inicialize int counter = 0;
gardarh
8
muito mais fácil agora em Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel
241

Se você estiver usando também há outra maneira de fazer isso.

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

O que ele faz é:

  • recebendo um Stream<Integer>da lista
  • obtendo um IntStreammapeando cada elemento para si mesmo (função de identidade), descompactando o intvalor retido por cada Integerobjeto (feito automaticamente desde o Java 5)
  • obtendo a matriz intchamandotoArray

Você também pode chamar explicitamente intValueatravés de uma referência de método, ou seja:

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

Também vale a pena mencionar que você pode obter um NullPointerExceptionse tiver alguma nullreferência na lista. Isso pode ser facilmente evitado adicionando uma condição de filtragem ao pipeline de fluxo como este:

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

Exemplo:

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]
Alexis C.
fonte
Vejo que isso pode ser usado para doubletipos; não há equivalente para floattipos?
code_dredd
Viu o benefício do Java 8 por sua explicação elaborada.
27919 Eugene
E é por isso que a API Java 8+ Stream é linda.
Pranav A. 19/04
67

Google Guava

O Google Guava fornece uma maneira elegante de fazer isso ligando Ints.toArray.

List<Integer> list = ...;
int[] values = Ints.toArray(list);
Snehal
fonte
6
Eu acho que essa será a resposta para mim - vou usar uma biblioteca em uma função de copiar e colar a qualquer dia. Especialmente uma biblioteca que um projeto de tamanho decente provavelmente já usa. Espero que esta resposta obtenha mais votos positivos e visibilidade no futuro.
23813 Sean Connolly
61

O Apache Commons possui uma classe ArrayUtils, que possui um método toPrimitive () que faz exatamente isso.

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

No entanto, como Jon mostrou, é muito fácil fazer isso sozinho, em vez de usar bibliotecas externas.

Björn
fonte
2
Observe que esta abordagem fará duas cópias completas da sequência: um inteiro [] criado por toArray e um int [] criado dentro de toPrimitive. A outra resposta de Jon apenas cria e preenche uma matriz. Algo a considerar se você tiver listas grandes e o desempenho for importante.
paraquat
Avaliei o desempenho usando ArrayUtils x java puro e em pequenas listas (<25 elementos) java puro é mais de 100 vezes mais rápido. Para 3k elementos java puro ainda é quase 2 vezes mais rápido ... (ArrayList <Integer> -> int [])
Oskar Lund
@paraquat & Oskar Lund que não estão realmente corretos. Sim, o código fornecido criará duas matrizes, mas essa abordagem não. O problema neste código aqui é o uso de uma matriz de comprimento zero como argumento. O código-fonte ArrayList.toArray mostra que, se o conteúdo couber, a matriz original será usada. Penso que, em uma comparação justa, você achará esse método tão eficiente (se não mais) e, é claro, menos código para manter.
23813 Sean Connolly
PS: um bom post relacionado #
Sean Connolly
1
Qual é o objetivo do novo número inteiro [0]?
Adam Hughes
41

Acredito que iterar usando o iterador da Lista é uma idéia melhor, pois list.get(i)pode ter um desempenho ruim, dependendo da implementação da Lista:

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

usar Dollar deve ser bastante simples:

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

Estou planejando melhorar o DSL para remover a toArray()chamada intermediária

dfa
fonte
1
Ei, só queria dizer que eu não tinha visto Dollar antes, mas definitivamente estou experimentando meu próximo projeto. Essa é uma api bacana você ir lá, mantenha o bom trabalho :)
Bart Vandendriessche
4

Isso funciona bem para mim :)

Encontrado em 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));
    }
}
angelhernandez
fonte
3

Surpreende-me que incentivemos métodos personalizados únicos sempre que uma biblioteca perfeitamente boa e bem usada, como o Apache Commons, já resolveu o problema. Embora a solução seja trivial, se não absurda, é irresponsável incentivar esse comportamento devido à manutenção e acessibilidade a longo prazo.

Basta ir com o Apache Commons

Andrew F.
fonte
7
Eu concordo com o comentarista anterior. Você não apenas arrasta no Apache Commons, mas também se traduz facilmente em um grande conjunto de dependências transitivas que também precisam ser arrastadas. Recentemente, eu pude remover um incrível número de dependências substituindo uma linha de código :-( As dependências são caras e escrever código básico como este é uma boa prática
Peter Kriens
1
Concordou com @PeterKriens. Se qualquer coisa, a culpa é em Java por não apoiar conversões simples como este em seus tipos de dados padrão
Adam Hughes
3

Se você estiver usando Coleções Eclipse , poderá usar o collectInt()método para alternar de um contêiner de objeto para um contêiner 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 você pode converter seu ArrayListem um FastList, pode se livrar do adaptador.

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

Nota: Sou responsável por coleções do Eclipse.

Craig P. Motlin
fonte
3

Java 8:

int[] intArr = Arrays.stream(integerList).mapToInt(i->i).toArray();
EssaidiM
fonte
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));

Resultado:

Matriz de ints primitivos: [7, 9, 13]

O mesmo vale para uma matriz de longou double, mas não para matrizes de boolean, char, byte, shortou float. Se você tem uma lista realmente grande, há até um parallelSetAllmétodo que você pode usar.

Para mim, isso é bom e elegante o suficiente para que eu não queira obter uma biblioteca externa nem usar fluxos para ela.

Link da documentação: Arrays.setAll(int[], IntUnaryOperator)

Ole VV
fonte
1

Você pode simplesmente copiá-lo para uma matriz:

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

Não é muito chique; mas, ei, funciona ...

sagiksp
fonte
1

Uma solução simples de uma linha é:

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

Este segmento de código está funcionando para mim, tente o seguinte:

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

Vale mencionar que ArrayList deve ser declarado assim:

ArrayList<Integer> list = new ArrayList<>();
user3444748
fonte
5
Olá, apenas um lembrete gentil de que o OP quer uma matriz primitiva, não uma matriz de objetos.
OLIVER.KOO
3
Primitivo int não invólucro Inteiro!
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());
    }
CodeMadness
fonte
1
Esta resposta não funciona, ele retorna uma matriz com um único elemento em vez de vários elementos.
Mysticial
Por que usar um StringBuffer? Por que converter o número inteiro em uma string e, em seguida, em um número inteiro e, em seguida, em um int e, em seguida, em um número inteiro novamente? Por que usar uma matriz com um único elemento e por que fazer um loop sobre essa matriz de elemento único quando ele contém apenas um elemento? Por que converter números inteiros em objetos no loop externo? Há tantas perguntas aqui. @CodeMadness é apenas uma conta troll?
Victor Zamanian
-5
Integer[] arr = (Integer[]) x.toArray(new Integer[x.size()]);

acesso arrcomo normal int[].

snn
fonte
5
isso não responder à pergunta, a pergunta era sobre a conversão de tipo primitivo (int)
Asaf