Arrays.asList () массива - PullRequest
       46

Arrays.asList () массива

37 голосов
/ 08 августа 2009

Что не так с этим преобразованием?

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

Я сделал это после прочтения решения, найденного в Создать ArrayList из массива . Вторая строка (сортировка) в getTheNumber(...) вызывает следующее исключение:

Исключение в потоке "main" java.lang.ClassCastException: [Я не могу быть преобразован в java.lang.Comparable]

Что здесь не так? Я понимаю, что сортировка может быть сделана с Arrays.sort(), мне просто любопытно:

Ответы [ 9 ]

41 голосов
/ 08 августа 2009

Рассмотрим следующий упрощенный пример:

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

В строке println это печатает что-то вроде «[[I @ 190d11]», что означает, что вы фактически создали ArrayList, который содержит массивы int .

Ваша IDE и компилятор должны предупреждать о непроверенных назначениях в этом коде. Вы всегда должны использовать new ArrayList<Integer>() или new ArrayList<>() вместо new ArrayList(). Если бы вы использовали его, произошла бы ошибка компиляции из-за попытки передать List<int[]> в конструктор.

Не существует автобокса от int[] до Integer[], и в любом случае автобокс является только синтаксическим сахаром в компиляторе, поэтому в этом случае вам нужно сделать копию массива вручную:

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);
}
9 голосов
/ 08 августа 2009

Вы пытаетесь привести int [] к Integer [], это невозможно.

Вы можете использовать ArrayUtils для commons-lang, чтобы преобразовать целые числа в целые числа перед получением списка из массива:

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);
}    
8 голосов
/ 08 августа 2009

Есть две причины этого исключения:

1

Arrays.asList(factors) возвращает List<int[]>, где factors - массив int

2

Вы забыли добавить параметр типа к:

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

с:

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

В результате время компиляции Ошибка:

found   : java.util.List<int[]>
required: java.util.List<java.lang.Integer>
6 голосов
/ 08 августа 2009

Использовать java.utils.Arrays:

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

Или, если вы хотите быть эффективным, избегайте всего выделения объектов, просто выполняйте работу:

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;
}
2 голосов
/ 08 августа 2009

Я думаю, вы нашли пример, когда автобокс действительно не работает. Поскольку Arrays.asList(T... a) имеет параметр varargs, компилятор, по-видимому, считает int [] и возвращает List<int[]> с единственным элементом в нем.

Вы должны изменить метод на это:

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

и возможно добавьте это для совместимости

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 голосов
/ 08 августа 2009

Arrays.asList(factors) возвращает List<int[]>, а не List<Integer>. Поскольку вы делаете new ArrayList вместо new ArrayList<Integer>, вы не получаете ошибку компиляции, а создаете ArrayList<Object>, который содержит int[], и затем вы неявно приводите этот массив к ArrayList<Integer>. Конечно, при первой попытке использовать одно из этих «целых чисел» вы получаете исключение.

1 голос
/ 05 августа 2013

Это работает с 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);
}

В Java 4 нет vararg ...: -)

0 голосов
/ 08 августа 2009

Насколько я понимаю, функцию сортировки в классе коллекций можно использовать только для сортировки коллекций, реализующих сопоставимый интерфейс.

Вы предоставляете ему массив целых чисел. Вы, вероятно, должны обернуть это вокруг одного из известных классов Wrapper, таких как Integer. Целочисленные реализации сопоставимы.

Прошло много времени с тех пор, как я работал над какой-то серьезной Java, однако чтение некоторых материалов по функции сортировки поможет.

0 голосов
/ 08 августа 2009

это из Java API «Вид

публичная статическая сортировка void (список списка) Сортирует указанный список в порядке возрастания в соответствии с естественным порядком его элементов. Все элементы в списке должны реализовывать интерфейс Comparable. Кроме того, все элементы в списке должны быть взаимно сопоставимы (то есть e1.compareTo (e2) не должно создавать исключение ClassCastException для любых элементов e1 и e2 в списке). "

это связано с реализацией интерфейса Comparable

...