数组的Arrays.asList()方法

39

这个转换有什么问题?

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

在阅读Create ArrayList from array的解决方案后,我制作了这个程序。在getTheNumber(...)函数的第二行(排序)中,会引起以下异常:

Exception in thread "main" java.lang.ClassCastException: [I cannot be cast to java.lang.Comparable]

出了什么问题?我知道可以使用Arrays.sort()进行排序,但我对这种方式很感兴趣。


哇,谢谢你们如此及时的回答!大家加油 :) - nbl
简短回答:因为int[]不是可比较的。 - gstackoverflow
9个回答

43

让我们考虑以下简化的例子:

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]”这样的内容,这意味着你实际上构造了一个包含int数组的ArrayList。

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

您的图片链接似乎已经损坏。如果您仍然拥有原始图片,请重新上传到stack.imgur,或者编辑您的答案使其在没有图片的情况下正常工作。谢谢。 - Ilmari Karonen
感谢您的通知。当前版本的IntelliJ IDEA给出了一种不同于我记得破损图像所包含的警告(如果我没记错,以前有一个Arrays.asList特定的警告),因此我编辑了答案,使其在没有图像的情况下工作。 - Esko Luontola

9

您正在尝试将 int[] 强制转换为 Integer[],这是不可能的。

您可以使用 commons-lang 的 ArrayUtils 将 int 转换为 Integer,再从数组中获取 List:

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

这个异常有两种可能的原因:

1

Arrays.asList(factors) 返回一个 List<int[]>,其中 factors 是一个整型数组

2

你忘记了为以下代码添加类型参数:

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

使用:

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

导致编译时错误的原因是:
找到的类型为:java.util.List<int[]>
所需的类型为:java.util.List<java.lang.Integer>

构造函数 ArrayList(List<int[]>) 是否存在?@dfa - MaheshVarma
@MaheshVarma 当然可以,但你需要在ArrayList中指定该类型:ArrayList<int[]> f = new ArrayList<int[]>(Arrays.asList(factors));。请记住,int[]只是Object的子类,因此它可以作为泛型类型。 - klaar

6

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

+1,因为这个解决方案比笨重的集合更适合问题。 - Matthias

2

我认为你已经发现了一个自动装箱无法正常工作的例子。因为Arrays.asList(T... a)有一个可变参数,编译器显然会将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
Arrays.asList(factors) 返回的是一个 List<int[]>,而不是一个 List<Integer>。由于你使用的是 new ArrayList 而不是 new ArrayList<Integer>,所以你不会因此得到编译错误,但实际上创建了一个包含 int[]ArrayList<Object>,然后你隐式地将该 arraylist 强制转换为 ArrayList<Integer>。当然,第一次尝试使用其中的一个“Integers”时,你会遇到异常。

1

这段代码适用于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

这是来自Java API的内容:

public static void sort(List list) 根据其元素的自然顺序,将指定的列表按升序排序。列表中的所有元素都必须实现Comparable接口。此外,列表中的所有元素必须是相互可比较的(也就是说,对于列表中的任何元素e1和e2,e1.compareTo(e2)不能抛出ClassCastException异常)。

它涉及实现Comparable接口。


0
据我所知,集合类中的排序函数只能用于实现可比较接口的集合排序。
您正在提供一个整数数组。 您应该将其包装在已知的包装器类之一中,例如Integer。 Integer实现了可比较接口。
自从我最后一次认真学习Java以来已经过了很长时间,但是阅读一些关于排序函数的资料会有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接