奇怪的Arrays.asList()行为

时间:2014-02-16 01:35:58

标签: java arrays sorting

我有这个方法:

//not related to the error, but included for reference
ArrayList<ArrayList<Color>> a = new ArrayList<ArrayList<Color>>(); 

void addColorToList(float[] j) //this array always length 3
{
    float[] k = Arrays.copyOf(j, 3);
    Arrays.sort(k);
            //Error in the following line
    a.get(Arrays.asList(j).indexOf(k[0])).add(new Color(j[0], j[1], j[2])); 
}

并出现此错误:

Exception in thread "AWT-EventQueue-1" 
        java.lang.ArrayIndexOutOfBoundsException: -1

我已确定我的代码始终使用-1调用a.get(),因为Arrays.asList(j). indexOf(k[0])找不到该元素。但是,我无法弄清楚为什么这不能像我期望的那样工作。我尝试打印出Arrays.asList(j)的结果,但我不确定结果如何:[[F@307af497]。谁能告诉我这是什么问题?

1 个答案:

答案 0 :(得分:3)

让我们从这开始:

  

我尝试打印出Arrays.asList(j)的结果,但我不确定结果如何:[[F @ 307af497]。

您正在使用(有效)toString()方法打印列表。所以...

  • 外部'['和']'来自列表格式。

  • 您有一个由一个元素组成的列表。

  • 该元素是float的数组。 ([F@307af497Object.toString()生成,[Ffloat[]类型的呈现方式......)


这实际上是一个重要的线索。 Arrays.asList(float [])返回一个“float []”列表......

但为什么?

嗯,因为这就是应该做的!!

Arrays.asList签名为Arrays.asList<T>(T ...)。这意味着它需要一个显式的T[] ...或一个零个或多个T个实例的序列,然后将它包装为Object[]。然后将Object[]打包为List<Object>(粗略地说)。

这里的关键是实际类型T 必须是引用类型...而不是基本类型。

但是您的代码似乎期待像Arrays.asList(float ...)这样的重载方法...并期望这会让您的float[]包裹为List<Float>

不幸的是,asList没有这样的重载。

所以实际发生的是:

  • 您的通话绑定到Arrays.asList<float[]>(float[] ...)

  • varargs导致j被包裹在一个数组中;即相当于new float[][]{j}

  • 结果是List<float[]> ...的一个实例,包含一个元素。


那么解决方案是什么?

一般......

  • 一种解决方案是将您的花车代表Float[]而不是float[]。理想情况下,您可以将此更改推回到首先创建数组的代码,等等。

  • 第二种解决方案是在调用float[]之前将Float[]转换为asList。这样做的简单方法是使用简单的循环。 (可能还有第三方库用于执行此操作。)缺点是:

    • 每次调用此方法时都需要进行转换,如果你多次调用它可能会很昂贵,并且

    • 原始数组与已包装的数组之间没有连接...如果您想通过列表包装器更新数组。

但在这种情况下,最佳解决方案就是简单地替换它:

    Arrays.asList(j).indexOf(k[0])

使用一个简单的循环迭代原始float[]测试,找到与k[0]匹配的条目。


这个故事的寓意:你可以通过努力寻找一个优雅的Java解决方案轻松拍摄自己。

通常,愚蠢的代码更好。 (两者都更快,更正确。)