Подтвердить что ты не робот

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

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

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(), мне просто интересно об этом.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

1

Arrays.asList(factors) возвращает a 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>

Ответ 4

Использовать 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;
}

Ответ 5

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

Ответ 6

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

Ответ 7

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

Ответ 8

это из Java API "Своего рода

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

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

Ответ 9

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

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

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