【问题标题】:Arrays.asList() of an array数组的 Arrays.asList()
【发布时间】: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[] 不可比较

标签: java arrays integer arraylist


【解决方案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 工作了,但是阅读一些有关排序功能的内容会有所帮助。

            【讨论】:

              猜你喜欢
              • 2011-07-27
              • 1970-01-01
              • 1970-01-01
              • 2014-10-18
              • 2015-06-26
              • 2013-04-11
              • 2013-05-20
              • 2010-12-05
              • 1970-01-01
              相关资源
              最近更新 更多