Como converter int [] para Inteiro [] em Java?

167

Eu sou novo em Java e muito confuso.

Eu tenho um grande conjunto de dados de comprimento 4 int[]e quero contar o número de vezes que cada combinação específica de 4 números inteiros ocorre. Isso é muito semelhante à contagem de frequências de palavras em um documento.

Eu quero criar um Map<int[], double>que mapeie cada int [] para uma contagem em execução, pois a lista é repetida, mas o Map não aceita tipos primitivos.

então eu fiz Map<Integer[], Double>

meus dados são armazenados como um ArrayList<int[]>modo meu loop deve ser algo como

ArrayList<int[]> data = ... // load a dataset`

Map<Integer[], Double> frequencies = new HashMap<Integer[], Double>();

for(int[] q : data) {

    // **DO SOMETHING TO convert q from int[] to Integer[] so I can put it in the map

    if(frequencies.containsKey(q)) {
    frequencies.put(q, tfs.get(q) + p);
    } else {
        frequencies.put(q, p);
    }
}

Não tenho certeza do código necessário no comentário para fazer esse trabalho converter um int[]para um Integer[]. Ou talvez eu esteja fundamentalmente confuso sobre a maneira correta de fazer isso.

Jonik
fonte
6
"Eu quero criar um mapa <int [], duplo> ... mas o mapa não aceita tipos primitivos." Como um dos posts abaixo apontou, int [] não é um tipo primitivo, portanto esse não é o problema real. O verdadeiro problema é que as matrizes não substituem .equals () para comparar os elementos. Nesse sentido, a conversão para Inteiro [] (como o título diz) não ajuda. No código acima, frequencies.containsKey (q) ainda não funcionaria conforme o esperado, porque usa .equals () para comparar. A solução real é não usar matrizes aqui.
Newacct
Não queira enviar spam com outra resposta, mas vale a pena notar que agora existe um exemplo de documentação sobre isso.
Mureinik

Respostas:

189

Java 8 nativo (uma linha)

Com o Java 8, int[]pode ser convertido para Integer[]facilmente:

int[] data = {1,2,3,4,5,6,7,8,9,10};

// To boxed array
Integer[] what = Arrays.stream( data ).boxed().toArray( Integer[]::new );
Integer[] ever = IntStream.of( data ).boxed().toArray( Integer[]::new );

// To boxed list
List<Integer> you  = Arrays.stream( data ).boxed().collect( Collectors.toList() );
List<Integer> like = IntStream.of( data ).boxed().collect( Collectors.toList() );

Como outros afirmaram, Integer[]geralmente não é uma boa chave do mapa. Mas no que diz respeito à conversão, agora temos um código relativamente limpo e nativo.

Sheepy
fonte
3
Enquanto isso, é o caminho correto. Se você precisar da Matriz Inteira como uma lista, poderá escrever:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
aw-think
Para converter a um Integer[]eu realmente sugerir o uso seguinte sintaxe: Integer[] boxed = IntStream.of(unboxed).boxed().toArray();Na forma semelhante como @NwDx
YoYo
1
@JoD. Sim, isso funciona. Mas IntStream.ofliga Arrays.streammesmo assim. Acho que tudo se resume à preferência pessoal - prefiro uma função substituída, alguns adoram usar classes mais explícitas.
Sheepy
2
Essa é uma solução louca, mas ótima! Obrigado!
Rugal
1
@VijayChavda A nova sintaxe, denominada referência de método , foi introduzida em 2014 com o Java 8 como parte do lambda ( JSR 335 Parte C ). Isso significa the "new" method (constructor) of the Integer[] class.
Sheepy 26/03
79

Se você deseja converter um int[]para um Integer[], não há uma maneira automatizada de fazer isso no JDK. No entanto, você pode fazer algo assim:

int[] oldArray;

... // Here you would assign and fill oldArray

Integer[] newArray = new Integer[oldArray.length];
int i = 0;
for (int value : oldArray) {
    newArray[i++] = Integer.valueOf(value);
}

Se você tiver acesso ao biblioteca Apache lang , poderá usar o ArrayUtils.toObject(int[])método como este:

Integer[] newArray = ArrayUtils.toObject(oldArray);
Eddie
fonte
71
essa é uma maneira desagradável de fazer um loop for.
22612 James Becwar
9
Isso é perfeitamente normal para cada um ... Não vejo a parte desagradável.
Dahaka
18
@ Dahaka, a maldade está em usar um iterador valueenquanto a variável de indexação iestiver lá.
Lcn 24/08/13
1
@ ICn, posso ver por que algumas pessoas não preferem esse estilo, mas o que o torna tão indesejável quanto desagradável?
Eddie
14
@icn, @Dahaka: O desagradável é que, como você já está usando uma variável de índice incremental, não há necessidade de usar um para cada um também; embora pareça bonito e simples no código, nos bastidores, que envolve sobrecarga desnecessária. Um for (int i...)loop tradicional seria mais eficiente aqui.
Daiscog
8

Presumivelmente, você deseja que a chave do mapa corresponda ao valor dos elementos em vez da identidade da matriz. Nesse caso, você deseja algum tipo de objeto que define equalse hashCodecomo seria de esperar. O mais fácil é converter para um List<Integer>, um ArrayListuso ou melhor Arrays.asList. Melhor que isso, você pode introduzir uma classe que represente os dados (semelhante a, java.awt.Rectanglemas eu recomendo tornar as variáveis ​​privadas como finais e também a classe).

Tom Hawtin - linha de orientação
fonte
Ah, aqui está uma questão de conversão de matriz, ao contrário: stackoverflow.com/questions/564392/…
Tom Hawtin - tackline
8

Usando loop for regular sem bibliotecas externas:

Converter int [] em Inteiro []:

int[] primitiveArray = {1, 2, 3, 4, 5};
Integer[] objectArray = new Integer[primitiveArray.length];

for(int ctr = 0; ctr < primitiveArray.length; ctr++) {
    objectArray[ctr] = Integer.valueOf(primitiveArray[ctr]); // returns Integer value
}

Converta Inteiro [] para int []:

Integer[] objectArray = {1, 2, 3, 4, 5};
int[] primitiveArray = new int[objectArray.length];

for(int ctr = 0; ctr < objectArray.length; ctr++) {
    primitiveArray[ctr] = objectArray[ctr].intValue(); // returns int value
}
prata
fonte
6

Eu estava errado em uma resposta anterior. A solução adequada é usar essa classe como uma chave no mapa, envolvendo a int real [].

public class IntArrayWrapper {
        int[] data;

        public IntArrayWrapper(int[] data) {
            this.data = data;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            IntArrayWrapper that = (IntArrayWrapper) o;

            if (!Arrays.equals(data, that.data)) return false;

            return true;
        }

        @Override
        public int hashCode() {
            return data != null ? Arrays.hashCode(data) : 0;
        }
    }

e altere seu código assim:

   Map<IntArrayWrapper, Double > freqs = new HashMap<IntArrayWrapper, Double>();

    for (int[] data : datas) {
        IntArrayWrapper wrapper = new IntArrayWrapper(data);

        if ( freqs.containsKey(wrapper)) {
            freqs.put(wrapper, freqs.get(wrapper) + p);
        }

        freqs.put(wrapper, p);
    }
Mihai Toader
fonte
1
Eu faria a aula final e a final particular em campo. Faça uma cópia defensiva da matriz no construtor (clone). E basta retornar o valor de Arrays.equals em vez de ter essa instrução if peculiar. toString seria bom.
Tom Hawtin - tackline
1
Ah, e jogue um NPE do construtor (provavelmente chamando clone) para dados nulos, e não faça a verificação no hashCode.
Tom Hawtin - tackline
Verdadeiro .. Mas o código para iguais, hashCode é gerado pelo IDEA :-). Funciona corretamente.
Mihai Toader
6
  1. Converter int [] em Inteiro []

    public static Integer[] toConvertInteger(int[] ids) {
    
      Integer[] newArray = new Integer[ids.length];
         for (int i = 0; i < ids.length; i++) {
           newArray[i] = Integer.valueOf(ids[i]);
         }
       return newArray;
    }
  2. Converter Inteiro [] em int []

    public static int[] toint(Integer[] WrapperArray) {
    
       int[] newArray = new int[WrapperArray.length];
          for (int i = 0; i < WrapperArray.length; i++) {
             newArray[i] = WrapperArray[i].intValue();
          }
       return newArray;
    }
Harsh
fonte
2
Isso é impreciso devido ao autoboxing. No 1º exemplo, você pode simplesmente fazer newArray[i] = ids[i];e na segunda um newArray[i] = WrapperArray[i]:)
Eel Lee
3

Em vez de escrever seu próprio código, você pode usar um IntBuffer para agrupar o int [] existente sem precisar copiar os dados em uma matriz Inteira

int[] a = {1,2,3,4};
IntBuffer b = IntBuffer.wrap(a);

O IntBuffer implementa comparáveis ​​para que você possa usar o código que você já escreveu. Os mapas formalmente comparam chaves de modo que a.equals (b) seja usado para dizer que duas chaves são iguais, portanto, dois IntBuffers com matriz 1,2,3 - mesmo que as matrizes estejam em locais diferentes de memória - sejam iguais e assim será trabalhe para o seu código de frequência.

ArrayList<int[]> data = ... // load a dataset`

Map<IntBuffer, Double> frequencies = new HashMap<IntBuffer, Double>();

for(int[] a : data) {

    IntBuffer q = IntBuffer.wrap(a);

    if(frequencies.containsKey(q)) {
        frequencies.put(q, tfs.get(q) + p);
    } else {
        frequencies.put(q, p);
    }

}

espero que ajude

Chris
fonte
2

Não sei por que você precisa de um duplo no seu mapa. Em termos do que você está tentando fazer, você tem um int [] e deseja apenas contar quantas vezes cada sequência ocorre? Por que isso exigia um Double de qualquer maneira?

O que eu faria é criar um wrapper para a matriz int com os métodos .equals e .hashCode adequados para levar em conta o fato de que o objeto int [] em si não considera os dados em sua versão desses métodos.

public class IntArrayWrapper {
    private int values[];

    public IntArrayWrapper(int[] values) {
        super();
        this.values = values;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + Arrays.hashCode(values);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        IntArrayWrapper other = (IntArrayWrapper) obj;
        if (!Arrays.equals(values, other.values))
            return false;
        return true;
    }

}

E, em seguida, use o multiset do google goiaba, que se destina exatamente ao objetivo de contar as ocorrências, desde que o tipo de elemento inserido tenha os métodos .equals e .hashCode adequados.

List<int[]> list = ...;
HashMultiset<IntArrayWrapper> multiset = HashMultiset.create();
for (int values[] : list) {
    multiset.add(new IntArrayWrapper(values));
}

Em seguida, para obter a contagem para qualquer combinação específica:

int cnt = multiset.count(new IntArrayWrapper(new int[] { 0, 1, 2, 3 }));
Matt
fonte
IntArrayWrapperDefinitivamente, essa é a abordagem correta para o uso de uma int[]matriz como chave de hash, mas deve-se mencionar que esse tipo já existe ... Você pode usá-lo para agrupar uma matriz e não apenas a possui hashCodee equalsé até comparável.
21916 Holger
2

Atualização: Embora o abaixo seja compilado, ele lança um ArrayStoreExceptionem tempo de execução. Que pena. Vou deixar para referência futura.


Convertendo um int[], para um Integer[]:

int[] old;
...
Integer[] arr = new Integer[old.length];
System.arraycopy(old, 0, arr, 0, old.length);

Devo admitir que fiquei um pouco surpreso que isso compila, dado System.arraycopyser de nível baixo e tudo mais, mas faz. Pelo menos em java7.

Você pode converter para o outro lado com a mesma facilidade.

Thomas Ahle
fonte
2
Não vejo muito valor em manter esta resposta "para referência" quando ela não funciona. A documentação para System.arraycopy () ainda afirma que não funcionará para esse fim.
Zero3
2

Isso funcionou como um encanto!

int[] mInt = new int[10];
Integer[] mInteger = new Integer[mInt.length];

List<Integer> wrapper = new AbstractList<Integer>() {
    @Override
    public int size() {
        return mInt.length;
    }

    @Override
    public Integer get(int i) {
        return mInt[i];
    }
};

wrapper.toArray(mInteger);
Itamar Borges
fonte
Oi Tunaki, você pode explicar o código acima para mim? quando eu corro pelo depurador, vejo que o método get e size é chamado automaticamente, ou seja, sem que eles sejam chamados explicitamente !! como assim?! você pode explicar, por favor?
forkdbloke
0

Converter int [] em Inteiro []:

    import java.util.Arrays;
    ...

    int[] aint = {1,2,3,4,5,6,7,8,9,10};
    Integer[] aInt = new Integer[aint.length];

    Arrays.setAll(aInt, i -> aint[i]);
zemiak
fonte
-1

você não precisa. int[]é um objeto e pode ser usado como uma chave dentro de um mapa.

Map<int[], Double> frequencies = new HashMap<int[], Double>();

é a definição adequada do mapa de frequências.

Isso estava errado :-). A solução adequada também é publicada :-).

Mihai Toader
fonte
Muito obrigado pela sua resposta. Tentei isso primeiro e ele compilou bem, mas parece frequencies.containsKey(q)que sempre seria falso, mesmo que eu tenha puta mesma matriz duas vezes - há alguma falha aqui envolvendo a definição de igualdade de java com int [] 's?
1
(Dica, (new int [0]). Equals (new int [0]) é false; (new ArrayList <Integer> ()). Equals (new ArrayList <String> ()) é true.
Tom Hawtin - tackline
1
Má ideia, pois a comparação de matrizes é baseada na igualdade de referência . É por isso que Arrays.equals () existe ...
sleske
Droga :-). Eu estava esperando que eu estivesse certa. A declaração está correta, mas a semântica está errada por causa da igualdade de referência.
Mihai Toader
-3

Basta usar:

public static int[] intArrayToIntegerArray(int[] a) {
    Integer[] b = new Integer[a.length];
    for(int i = 0; i < array.length; i++){
        b[i] = a[i];
    }
    return g;
}
Lurzapps
fonte