70

我正在实现一个接口,其功能类似于可以包含一种对象类型的表。该接口指定以下功能:

double[] getDoubles(int columnIndex);

我感到困惑的是,在我的实现中,我将表数据存储在二维Object数组 ( Object[][] data) 中。当我需要返回值时,我想做以下事情(假设getDoubles()只会在包含双精度的列上调用,所以不会有ClassCastExceptions):

double[] getDoubles(int columnIndex) {
    return (double[]) data[columnIndex];
}

但是 - Java 不允许Object[]强制转换为double[]. 将其转换Double[]为可以,因为它Double是一个对象而不是原语,但我的接口指定数据将作为double[].

所以我有两个问题:

  1. 有什么方法可以从Object[][]表中获取列数据并返回基元数组?
  2. 如果我确实将接口更改为 return Double[],会对性能产生任何影响吗?
4

8 回答 8

92

如果您不介意使用 3rd 方库,commons-lang 具有 ArrayUtils 类型和各种操作方法。

Double[] doubles;
...
double[] d = ArrayUtils.toPrimitive(doubles);

还有互补的方法

doubles = ArrayUtils.toObject(d);

编辑:回答剩下的问题。这样做会有一些开销,但除非数组真的很大,否则你不应该担心它。在重构之前先测试它是否有问题。

实现您实际询问的方法会给出这样的结果。

double[] getDoubles(int columnIndex) {
    return ArrayUtils.toPrimitive(data[columnIndex]);
}
于 2009-07-10T15:09:48.457 回答
53

在 Java 8 中,这是单行代码:

Double[] boxed = new Double[] { 1.0, 2.0, 3.0 };
double[] unboxed = Stream.of(boxed).mapToDouble(Double::doubleValue).toArray();

请注意,这仍然会遍历原始数组并创建一个新数组。

于 2015-05-08T06:55:13.993 回答
34

不幸的是,Double如果要将其转换为double[].

就性能而言,Java 中的装箱和拆箱原语需要一段时间。如果集合足够小,您将不会看到任何性能问题。

于 2009-07-10T14:52:19.407 回答
8

您可以使用 for each 循环来构造一个相同大小的临时数组,然后将每个单独的元素转换为双精度,但它在数组中。

所以:

double[] tempArray = new double[data[columnIndex].length];
int i = 0;
for(Double d : (Double) data[columnIndex]) {
  tempArray[i] = (double) d;
  i++;
}

如果我在这里错了,请纠正我。

于 2009-07-10T14:54:32.133 回答
3

如果您想返回 a double[],则需要创建 a new double[],填充它并返回它。

这可能是一个很好的架构决策。Object[]首先,将 an转换为 a没有多大意义Double[];它并不是真正的数组,Double因为其中也可能有Objects。其次,如果直接返回数组,用户代码可以修改它并改变对象的内部结构。

double[]由于拆箱和分配成本,主要的性能影响将是返回一个数组。

于 2009-07-10T14:53:51.400 回答
2

您可以利用 ArrayUtils 转换

Double[] d; // initialise
double[] array = ArrayUtils.toPrimitive(d);

无需循环整个数据。

于 2017-02-15T13:28:57.440 回答
1

除了 jjnguy 和 Eric Koslow 所说的之外,我没有什么可以补充到真正的问题上。

但只是附带说明:您提到将 Object 数组转换为 Double 数组。以下将不起作用:

Object[] oa=new Object[3];
oa[0]=new Double("1.0");
oa[1]=new Double("2.0");
oa[2]=new Double("3.0");
Double[] da=(Double[])oa;

最后一行将抛出一个类转换异常。尽管数组中的每个元素确实是 Double,但该数组是作为 Objects 数组创建的,而不是 Doubles 数组,因此强制转换是无效的。

于 2009-07-10T16:56:38.560 回答
0

我会支持 ArrayUtils 的答案,并补充说 1.5自动装箱文档via)有点显示没有内置方法:

如果除了从 SC 到 TC 的字符串转换之外没有允许的转换,则不允许从数组类型 SC[] 到数组类型 TC[] 的转换

于 2009-07-10T16:33:36.360 回答