Comment convertir int [] en Integer [] en Java?

167

Je suis nouveau sur Java et très confus.

J'ai un grand ensemble de données de longueur 4 int[]et je veux compter le nombre de fois que chaque combinaison particulière de 4 entiers se produit. Ceci est très similaire au comptage des fréquences de mots dans un document.

Je veux créer un Map<int[], double>qui mappe chaque int [] à un décompte au fur et à mesure que la liste est itérée, mais Map ne prend pas les types primitifs.

alors j'ai fait Map<Integer[], Double>

mes données sont stockées comme un ArrayList<int[]>donc ma boucle devrait être quelque chose comme

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

Je ne suis pas sûr de ce code que je dois au commentaire à faire ce travail pour convertir un int[]à un Integer[]. Ou peut-être que je suis fondamentalement confus quant à la bonne façon de procéder.

Jonik
la source
6
"Je veux créer un Map <int [], double> ... mais Map ne prend pas de types primitifs." Comme l'un des articles ci-dessous l'a souligné, int [] n'est pas un type primitif, ce n'est donc pas le vrai problème. Le vrai problème est que les tableaux ne remplacent pas .equals () pour comparer les éléments. En ce sens, la conversion en Integer [] (comme votre titre l'indique) ne vous aide pas. Dans le code ci-dessus, frequencies.containsKey (q) ne fonctionnerait toujours pas comme prévu car il utilise .equals () pour comparer. La vraie solution est de ne pas utiliser de tableaux ici.
newacct
Je ne veux pas envoyer de spam avec une autre réponse, mais il convient de noter qu'il existe maintenant un exemple de documentation à ce sujet.
Mureinik

Réponses:

189

Java 8 natif (une ligne)

Avec Java 8, int[]peut être converti Integer[]facilement en:

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

Comme d'autres l'ont indiqué, ce Integer[]n'est généralement pas une bonne clé de carte. Mais en ce qui concerne la conversion, nous avons maintenant un code relativement propre et natif.

Sheepy
la source
3
C'est en attendant la bonne manière. Si vous avez besoin du tableau d'entiers sous forme de liste, vous pouvez écrire:List<Integer> list = IntStream.of(q).boxed().collect(Collectors.toList());
aw-think
pour convertir en un, Integer[]je suggérerais en fait d'utiliser la syntaxe suivante: Integer[] boxed = IntStream.of(unboxed).boxed().toArray();De la même manière que @NwDx
YoYo
1
@JoD. Oui, ça marche. Mais IntStream.ofappelle Arrays.streamquand même. Je pense que cela se résume à une préférence personnelle - je préfère une fonction remplacée, certains aiment utiliser une classe plus explicite.
Sheepy
2
C'est une solution folle mais excellente! Je vous remercie!
Rugal
1
@VijayChavda La nouvelle syntaxe, appelée références de méthode , a été introduite en 2014 avec Java 8 dans le cadre de lambda ( JSR 335 Partie C ). Cela signifie the "new" method (constructor) of the Integer[] class.
Sheepy
79

Si vous souhaitez convertir un int[]en un Integer[], il n'existe pas de moyen automatisé de le faire dans le JDK. Cependant, vous pouvez faire quelque chose comme ceci:

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

Si vous avez accès à la bibliothèque Apache lang , vous pouvez utiliser la ArrayUtils.toObject(int[])méthode comme celle-ci:

Integer[] newArray = ArrayUtils.toObject(oldArray);
Eddie
la source
71
c'est une mauvaise façon de faire une boucle for.
James Becwar
9
C'est tout à fait normal pour chacun ... Je ne vois pas la partie désagréable.
Dahaka
18
@Dahaka, la méchanceté est d'utiliser un itérateur de tant valueque la variable d'indexation iest là.
lcn
1
@Icn, je peux voir pourquoi certaines personnes ne préféreraient pas ce style, mais qu'est-ce qui le rend si indésirable qu'il est méchant?
Eddie
14
@icn, @Dahaka: La méchanceté est que puisque vous utilisez déjà une variable d'index incrémentielle, il n'est pas nécessaire d'utiliser un for-each, aussi; bien que cela semble joli et simple dans le code, dans les coulisses, cela implique une surcharge inutile. Une for (int i...)boucle traditionnelle serait plus efficace ici.
daiscog
8

Vraisemblablement, vous voulez que la clé de la carte corresponde à la valeur des éléments au lieu de l'identité du tableau. Dans ce cas, vous voulez une sorte d'objet qui définit equalset hashCodecomme vous vous en doutez. Le plus simple est de convertir en une List<Integer>, une ArrayListou une meilleure utilisation Arrays.asList. Mieux que cela, vous pouvez introduire une classe qui représente les données (similaire java.awt.Rectanglemais je recommande de rendre les variables privées finales, et la classe finale aussi).

Tom Hawtin - Tacle
la source
Oh, voici une question de conversion de tableau, juste l'inverse: stackoverflow.com/questions/564392/...
Tom Hawtin - tackline
8

Utilisation de la boucle for régulière sans bibliothèques externes:

Convertissez un entier [] en un entier []:

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
}

Convertir un entier [] en un entier []:

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
}
argent
la source
6

J'avais tort dans une réponse précédente. La bonne solution consiste à utiliser cette classe comme clé dans la carte encapsulant le véritable int [].

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

et changez votre code comme ceci:

   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
la source
1
Je rendrais la classe finale et la finale privée sur le terrain. Faites une copie défensive du tableau dans le constructeur (cloner). Et renvoyez simplement la valeur de Arrays.equals plutôt que d'avoir cette instruction if particulière. toString serait bien.
Tom Hawtin - tackline
1
Oh et lancez un NPE du constructeur (appelant probablement clone) pour les données nulles, et ne pas avoir le check in hashCode.
Tom Hawtin - Tacle
Vrai .. Mais le code pour equals, hashCode est généré par IDEA :-). Cela fonctionne correctement.
Mihai Toader
6
  1. Convertir un entier [] en un entier []

    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. Convertir un entier [] en un entier []

    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;
    }
    
Dur
la source
2
Ceci est plutôt inexact en raison de l'auto-box. Dans le 1er exemple, vous pouvez simplement faire newArray[i] = ids[i];et dans le 2ème newArray[i] = WrapperArray[i]:)
Eel Lee
3

Plutôt que d'écrire votre propre code, vous pouvez utiliser un IntBuffer pour encapsuler l'int [] existant sans avoir à copier les données dans un tableau Integer

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

IntBuffer implémente des outils comparables afin que vous puissiez utiliser le code que vous avez déjà écrit. Mappe formellement les clés de comparaison telles que a.equals (b) est utilisé pour dire que deux clés sont égales, donc deux IntBuffers avec un tableau 1,2,3 - même si les tableaux sont dans des emplacements de mémoire différents - sont dits égaux et le sera travailler pour votre code de fréquence.

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

}

J'espère que cela pourra aider

Chris
la source
2

Je ne sais pas pourquoi vous avez besoin d'un double dans votre carte. En termes de ce que vous essayez de faire, vous avez un int [] et vous voulez juste compter combien de fois chaque séquence se produit? Pourquoi cela nécessitait-il un Double de toute façon?

Ce que je ferais est de créer un wrapper pour le tableau int avec les méthodes .equals et .hashCode appropriées pour tenir compte du fait que l'objet int [] lui-même ne considère pas les données dans sa version de ces méthodes.

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

}

Et puis utilisez le multiset de google guava, qui est destiné exactement à compter les occurrences, à condition que le type d'élément que vous y mettez ait les méthodes .equals et .hashCode appropriées.

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

Ensuite, pour obtenir le décompte d'une combinaison particulière:

int cnt = multiset.count(new IntArrayWrapper(new int[] { 0, 1, 2, 3 }));
Mat
la source
C'est IntArrayWrappercertainement la bonne approche pour utiliser un int[]tableau comme clé de hachage, mais il faut mentionner qu'un tel type existe déjà … Vous pouvez l'utiliser pour envelopper un tableau et non seulement l'avoir hashCodeet equals, c'est même comparable.
Holger
2

Mise à jour: bien que ce qui suit compile, il lance un ArrayStoreExceptionà l'exécution. Dommage. Je vais le laisser pour référence future.


Conversion d'un int[], en un Integer[]:

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

Je dois admettre que j'ai été un peu surpris que cela compile, System.arraycopyétant donné le niveau inférieur et tout, mais c'est le cas. Au moins en java7.

Vous pouvez convertir dans l'autre sens tout aussi facilement.

Thomas Ahle
la source
2
Je ne vois pas grand intérêt à garder cette réponse «pour référence» quand cela ne fonctionne pas. La documentation de System.arraycopy () indique même que cela ne fonctionnera pas dans ce but.
Zero3 du
2

Cela a fonctionné comme un charme!

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
la source
Salut Tunaki, pouvez-vous s'il vous plaît expliquer le code ci-dessus pour moi? quand je lance le débogueur, je vois que la méthode get et size est appelée automatiquement, c'est-à-dire sans qu'elles soient appelées explicitement !! comment?! pouvez-vous s'il vous plaît expliquer?
forkdbloke
0

Convertissez un entier [] en un entier []:

    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
la source
-1

vous n'en avez pas besoin. int[]est un objet et peut être utilisé comme clé à l'intérieur d'une carte.

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

est la bonne définition de la carte des fréquences.

C'était faux :-). La bonne solution est également affichée :-).

Mihai Toader
la source
Merci beaucoup pour votre réponse. J'ai essayé cela en premier et il s'est bien compilé, mais il semble que ce frequencies.containsKey(q)serait toujours faux même si j'ai putle même tableau deux fois - y a-t-il un problème impliquant la définition de l'égalité de Java avec les int []?
1
(Indice, (new int [0]). Equals (new int [0]) est faux; (new ArrayList <Integer> ()). Equals (new ArrayList <String> ()) est vrai.
Tom Hawtin - tackline
1
Mauvaise idée, car la comparaison de tableaux est basée sur l' égalité de référence . C'est pourquoi Arrays.equals () existe ...
sleske
Zut :-). J'espérais avoir raison. La déclaration est correcte mais la sémantique est fausse à cause de la chose d'égalité de référence.
Mihai Toader
-3

Utilisez simplement:

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
la source