web-dev-qa-db-fra.com

Arrays.asList () d'un tableau

Quel est le problème avec cette conversion?

public int getTheNumber(int[] factors) {
    ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));  
    Collections.sort(f);
    return f.get(0)*f.get(f.size()-1);
}

J'ai fait cela après avoir lu la solution trouvée dans Create ArrayList from array . La deuxième ligne (tri) dans getTheNumber(...) provoque l'exception suivante:

Exception dans le thread "principal" Java.lang.ClassCastException: [Je ne peux pas être casté en Java.lang.Comparable]

Qu'est-ce qui ne va pas ici? Je me rends compte que le tri pourrait être fait avec Arrays.sort(), je suis juste curieux de savoir celui-ci.

38
nbl

Prenons l'exemple simplifié suivant:

public class Example {
    public static void main(String[] args) {
        int[] factors = {1, 2, 3};
        ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));
        System.out.println(f);
    }
}

Sur la ligne println, cela imprime quelque chose comme "[[I @ 190d11]", ce qui signifie que vous avez réellement construit une ArrayList qui contient int tableaux.

Votre IDE et le compilateur doivent avertir des affectations non contrôlées dans ce code. Vous devez toujours utiliser new ArrayList<Integer>() ou new ArrayList<>() au lieu de new ArrayList() Si vous l'aviez utilisé, il y aurait eu une erreur de compilation en raison de la tentative de passer List<int[]> Au constructeur.

Il n'y a pas de boîte automatique de int[] À Integer[], Et de toute façon, la boîte automatique n'est que du sucre syntaxique dans le compilateur, dans ce cas, vous devez faire la copie du tableau manuellement:

public static int getTheNumber(int[] factors) {
    List<Integer> f = new ArrayList<Integer>();
    for (int factor : factors) {
        f.add(factor); // after autoboxing the same as: f.add(Integer.valueOf(factor));
    }
    Collections.sort(f);
    return f.get(0) * f.get(f.size() - 1);
}
42
Esko Luontola

Vous essayez de convertir int [] en entier [], ce n'est pas possible.

Vous pouvez utiliser les ArrayUtils de commons-lang pour convertir les entiers en entiers avant d'obtenir la liste à partir du tableau:

public int getTheNumber(int[] factors) {
    Integer[] integers = ArrayUtils.toObject(factors);
    ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(integers));
    Collections.sort(f);
    return f.get(0)*f.get(f.size()-1);
}    
9
Rich Seller

il y a deux causes à cette exception:

1

Arrays.asList(factors) renvoie un List<int[]>factors est un int array

2

vous avez oublié d'ajouter le paramètre type à:

ArrayList<Integer> f = new ArrayList(Arrays.asList(factors));

avec:

ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(factors));  

résultant en une erreur au moment de la compilation:

 trouvé: Java.util.List <int []> 
 requis: Java.util.List <Java.lang.Integer> 
8
dfa

Utilisez Java.utils.Arrays:

public int getTheNumber(int[] factors) {
    int[] f = (int[])factors.clone();
    Arrays.sort(f);
    return f[0]*f[(f.length-1];
}

Ou si vous voulez être efficace, évitez toute allocation d'objet, faites simplement le travail:

public static int getTheNumber(int[] array) {
    if (array.length == 0)
        throw new IllegalArgumentException();
    int min = array[0];
    int max = array[0];
    for (int i = 1; i< array.length;++i) {
        int v = array[i];
        if (v < min) {
            min = v;
        } else if (v > max) {
            max = v;
        }
    }
    return min * max;
}
6
Tom

Arrays.asList(factors) renvoie un List<int[]>, pas un List<Integer>. Puisque vous faites new ArrayList au lieu de new ArrayList<Integer> vous n'obtenez pas d'erreur de compilation pour cela, mais créez un ArrayList<Object> qui contient un int[] et vous avez ensuite implicitement jeté ce tableau sur ArrayList<Integer>. Bien sûr, la première fois que vous essayez d'utiliser l'un de ces "nombres entiers", vous obtenez une exception.

2
sepp2k

Je pense que vous avez trouvé un exemple où la boxe automatique ne fonctionne pas vraiment. Parce que Arrays.asList(T... a) a un paramètre varargs, le compilateur considère apparemment l'int [] et retourne un List<int[]> avec un seul élément.

Vous devez changer la méthode en ceci:

public int getTheNumber(Integer[] factors) {
    ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(factors));  
    Collections.sort(f);
    return f.get(0) * f.get(f.size() - 1);
}

et éventuellement ajouter ceci pour la compatibilité

public int getTheNumber(int[] factors) {
    Integer[] factorsInteger = new Integer[factors.length];
    for(int ii=0; ii<factors.length; ++ii) {
        factorsInteger[ii] = factors[ii];
    }

    return getTheNumber(factorsInteger);
}
2
Robert Petermeier

Cela fonctionne de Java 5 à 7:

public int getTheNumber(Integer... factors) {
    ArrayList<Integer> f = new ArrayList<Integer>(Arrays.asList(factors));
    Collections.sort(f);
    return f.get(0)*f.get(f.size()-1);
}

Dans Java 4 il n'y a pas de vararg ... :-)

1

cela provient de Java API "sort

public static void sort (List list) Trie la liste spécifiée dans l'ordre croissant, selon l'ordre naturel de ses éléments. Tous les éléments de la liste doivent implémenter l'interface Comparable. En outre, tous les éléments de la liste doivent être mutuellement comparables (c'est-à-dire que e1.compareTo (e2) ne doit pas lever d'exception ClassCastException pour les éléments e1 et e2 de la liste). "

cela a à voir avec la mise en œuvre de l'interface comparable

0
CoDeR

Pour autant que je le comprenne, la fonction de tri dans la classe de collection ne peut être utilisée que pour trier les collections implémentant l'interface comparable.

Vous lui fournissez un tableau d'entiers. Vous devriez probablement envelopper cela dans l'une des classes Wrapper connues telles que Integer. Entier implémente comparable.

Cela fait longtemps que je n'ai pas travaillé sur du Java sérieux, mais lire quelques informations sur la fonction de tri peut aider.

0
Kevin Boyd