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(...)导致以下异常:

线程“主”java.lang.ClassCastException 中的异常:[我无法转换为 java.lang.Comparable]

这里有什么问题?我确实意识到可以使用 进行排序Arrays.sort(),我只是对这个感到好奇。

4

9 回答 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 arrays的 ArrayList 。

您的 IDE 和编译器应该警告该代码中未经检查的分配。您应该始终使用new ArrayList<Integer>()ornew ArrayList<>()代替new ArrayList(). 如果你使用过它,就会因为试图传递List<int[]>给构造函数而出现编译错误。

int[]从to没有自动装箱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);
}
于 2009-08-08T12:44:29.843 回答
9

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

在从数组中获取列表之前,您可以使用 commons-lang 的 ArrayUtils 将整数转换为整数:

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);
}    
于 2009-08-08T12:41:56.880 回答
8

此异常有两个原因:

1

Arrays.asList(factors)返回List<int[]>一个intfactors数组

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>
于 2009-08-08T12:49:16.507 回答
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;
}
于 2009-08-08T12:43:36.320 回答
2

Arrays.asList(factors)返回 a List<int[]>,而不是 a List<Integer>。由于您正在这样做new ArrayList而不是new ArrayList<Integer>因此不会出现编译错误,而是创建一个ArrayList<Object>包含 anint[]然后您将该 arraylist 隐式转换为ArrayList<Integer>. 当然,当您第一次尝试使用其中一个“整数”时,您会遇到异常。

于 2009-08-08T12:39:52.497 回答
2

我想你已经找到了一个自动装箱不起作用的例子。因为Arrays.asList(T... a)有一个 varargs 参数,所以编译器显然会考虑 int[] 并返回List<int[]>其中包含单个元素的 a 。

您应该将方法更改为:

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);
}
于 2009-08-08T13:36:16.863 回答
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 中没有可变参数... :-)

于 2013-08-04T21:19:27.993 回答
0

这是来自Java API“排序

public static void sort(List list) 将指定列表按照其元素的自然顺序升序排序。列表中的所有元素都必须实现 Comparable 接口。此外,列表中的所有元素必须相互可比较(即,e1.compareTo(e2) 不得为列表中的任何元素 e1 和 e2 抛出 ClassCastException)。

它与实现 Comparable 接口有关

于 2009-08-08T12:38:33.183 回答
0

据我了解,集合类中的排序函数只能用于对实现了可比较接口的集合进行排序。

您正在为它提供一个整数数组。您可能应该将其包装在已知的 Wrapper 类之一中,例如 Integer。整数实现可比较。

自从我从事一些严肃的 Java 工作以来已经有很长时间了,但是阅读有关排序功能的一些内容会有所帮助。

于 2009-08-08T12:39:00.047 回答