数组的 Arrays.asList()

Posted

技术标签:

【中文标题】数组的 Arrays.asList()【英文标题】:Arrays.asList() of an array 【发布时间】:2010-11-17 22:31: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(...) 中的第二行(排序)导致以下异常:

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

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

【问题讨论】:

哇,感谢您的即时答复!干杯,所有:) 简短回答:因为 int[] 不可比较 【参考方案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]" 的内容,这意味着您实际上已经构建了一个包含 int arrays 的 ArrayList。

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

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,或者只是编辑您的答案以使其在没有图像的情况下工作。谢谢。 感谢您的通知。当前版本的 IntelliJ IDEA 给出的警告与我记得的损坏图像不同(IIRC 曾经有一个 Arrays.asList 特定警告),所以我编辑了答案以在没有图像的情况下工作。【参考方案2】:

您正在尝试将 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);
    

【讨论】:

【参考方案3】:

这个异常有两个原因:

1

Arrays.asList(factors) 返回一个List&lt;int[]&gt;,其中factors 是一个int 数组

2

您忘记将类型参数添加到:

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

与:

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

导致编译时错误:

找到:java.util.List 必需:java.util.List

【讨论】:

构造函数ArrayList(List)是否存在? @dfa @MaheshVarma 是的,为什么不呢?但是您还需要在 ArrayList 中指定该类型:ArrayList&lt;int[]&gt; f = new ArrayList&lt;int[]&gt;(Arrays.asList(factors));。永远记住int[] 只是Object 的子类,所以它被允许作为泛型类型。【参考方案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;

【讨论】:

+1,因为这个解决方案确实比不方便的 Collections 更适合这个问题。【参考方案5】:

我认为您已经找到了一个自动装箱不起作用的示例。因为 Arrays.asList(T... a) 有一个 varargs 参数,所以编译器显然会考虑 int[] 并返回一个包含单个元素的 List&lt;int[]&gt;

你应该把方法改成这样:

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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案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 中没有可变参数... :-)

【讨论】:

【参考方案8】:

这是来自 Java API "排序

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

这与实现 Comparable 接口有关

【讨论】:

【参考方案9】:

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

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

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

【讨论】:

以上是关于数组的 Arrays.asList()的主要内容,如果未能解决你的问题,请参考以下文章

Java Arrays.asList() 的避雷

Java-Arrays类-Arrays.asList()方法详解

使用Arrays.asList的优点和缺点

Arrays.asList的用法

Arrays类--Arrays.asList()方法使用

使用Arrays.asList方法使用Stream打印int数组[复制]