我正在实现一个接口,其功能类似于可以包含对象类型的表。接口指定以下功能:
double[] getDoubles(int columnIndex);
我感到困惑的是,在我的实现中,我将表数据存储在2D Object
数组(Object[][] data
)中。当我需要返回值时,我想执行以下操作(假设只在包含双精度的列上调用getDoubles()
,因此不会有ClassCastExceptions
):
double[] getDoubles(int columnIndex) {
return (double[]) data[columnIndex];
}
但是 - Java不允许Object[]
强制转换为double[]
。将其转换为Double[]
是可以的,因为Double
是一个对象而不是一个原语,但是我的接口指定数据将作为double[]
返回。
所以我有两个问题:
Object[][]
表中获取列数据并返回基元数组?Double[]
,会对性能产生任何影响吗?答案 0 :(得分:83)
如果你不介意使用第三方库,那么commons-lang的ArrayUtils类型有各种操作方法。
Double[] doubles;
...
double[] d = ArrayUtils.toPrimitive(doubles);
还有补充方法
doubles = ArrayUtils.toObject(d);
编辑:回答其余问题。这样做会有一些开销,但除非阵列非常大,否则你不必担心它。在重构之前先测试它是否存在问题。
实施您实际询问过的方法会产生类似的结果。
double[] getDoubles(int columnIndex) {
return ArrayUtils.toPrimitive(data[columnIndex]);
}
答案 1 :(得分:42)
在Java 8中,这是一行的:
Double[] boxed = new Double[] { 1.0, 2.0, 3.0 };
double[] unboxed = Stream.of(boxed).mapToDouble(Double::doubleValue).toArray();
请注意,这仍会迭代原始数组并创建一个新数组。
答案 2 :(得分:33)
不幸的是,如果您要将Double
转换为double[]
,则需要遍历整个列表并取消{{1}}。
就性能而言,Java中的装箱和拆箱原语有一些时间。如果该集合足够小,您将看不到任何性能问题。
答案 3 :(得分:7)
你可以使用a for each循环来构造一个相同大小的临时数组,然后将每个单独的元素转换为double,但是在数组中。
SO:
double[] tempArray = new double[data[columnIndex].length];
int i = 0;
for(Double d : (Double) data[columnIndex]) {
tempArray[i] = (double) d;
i++;
}
如果我在这里错了,请纠正我。
答案 4 :(得分:3)
如果您想要返回double[]
,则需要创建一个new double[]
,填充它,然后返回。
这可能是一个很好的架构决策。首先,将Object[]
强加给Double[]
并没有多大意义;它不是Double
的数组,因为它也可能有Object
个。其次,如果直接返回数组,用户代码可以修改它并改变对象的内部结构。
主要的性能影响是返回double[]
数组,原因是取消装箱和分配成本。
答案 5 :(得分: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数组创建的,而不是双打数组,因此转换无效。
答案 6 :(得分:0)
我会先回答ArrayUtils的答案并补充一点,1.5 autoboxing documentation(via)有点显示没有内置方式:
如果没有允许,则不允许从数组类型SC []转换为数组类型TC [] 除了从SC到TC的字符串转换之外的转换
答案 7 :(得分:0)
您可以使用ArrayUtils进行转换
Double[] d; // initialise
double[] array = ArrayUtils.toPrimitive(d);
无需循环整个数据。