没有任何捷径可以做得很好吗?
那个丑陋的两个循环(一个循环读取pmList,第二个循环添加到markupArray)是唯一的选择(而不是ArrayUtils)。
ArrayList<Double> pmList = new ArrayList<Double>();
pmList.add(0.1); // adding through a loop in real time.
pmList.add(0.1);
pmList.add(0.1);
pmList.add(0.1);
double[] markupArray = new double[pmList.size()];
arkupArray = pmList.toArray(markupArray); // This says The method toArray(T[]) in the type ArrayList<Double> is not applicable for the arguments (double[])
答案 0 :(得分:3)
只需使用Double[]
数组,而不是double[]
,那么一切正常。如果您提前知道列表的大小,也可以跳过列表并直接插入到数组中。甚至可能值得两次遍历输入:一次用于检索其大小,一次用于插入。
自动装箱仅适用于基本类型,不适用于基本类型数组。 double[]
数组不是T[]
数组,因为类型参数T
必须始终为Object
。虽然double
可以自动装箱到T
(T=Double
),但double[]
无法自动装箱到T[]
。
数组未自动装箱的原因可能是此操作非常昂贵:装箱阵列意味着创建一个新阵列并装箱每个元素。对于大型阵列,这会带来巨大的性能影响。您不希望隐式执行如此昂贵的操作,因此不会对数组进行自动装箱。另外,装入一个完整的数组会产生一个新的数组。因此,在写入新数组时,更改将不会写入旧数组。所以你看,数组装有一些语义问题,所以不支持它。
如果必须返回double[]
数组,则必须编写自己的函数或使用像Guava这样的第三方库(请参阅msandiford的答案)。 Java Collections框架没有(un)装箱数组的方法。
答案 1 :(得分:1)
您可以使用TDoubleArraList或guava的原始列表集合。
您还可以在一个循环中预先确定大小,并将值添加到另一个循环中。
答案 2 :(得分:1)
为什么不制作自己的捷径?
static double[] doubleListToArray(List<Double> list) {
int k = 0;
double[] result = new double[list.size()];
for(double value : list)
result[k++] = value;
return result;
}
答案 3 :(得分:1)
Google guava有Doubles#asList(...)
和Doubles#toArray(...)
,分别提供从double[]
到List<Double>
和从Collection<? extends Number>
到double[]
的转化。
答案 4 :(得分:1)
你是对的,初看起来不是很直观。但是,此限制与Java语言实现泛型类型和自动装箱的方式有关:
通用类型在运行时被删除。这意味着任何ArrayList<Double>
都由单个已编译的Java类ArrayList
表示,该类与ArrayList
的其他通用表示形式共享,例如ArrayList<String>
。因此,编译后的方法ArrayList::toArray
不会(也绝不)知道实例表示的泛型类型,因为单个编译方法必须适用于任何泛型类型。因为元素可以是String
或Double
,所以您需要为方法提供一个数组。然后,该方法可以在运行时检查目标数组的类型,并检查在运行时填充到数组中的元素是否可分配给数组的组件类型。所有这些逻辑都可以通过单个编译方法实现。
其次,自动装箱和-unboxing只在编译时存在。这意味着陈述
Integer i = 42;
int j = i;
像编写一样编译
Integer i = new Integer(42);
int j = i.intValue();
Java编译器会为您添加装箱说明。 Java运行时应用稍微不同的类型系统,其中不考虑装箱。因此,我们在(1)中提到的单个编译方法ArrayList::toArray
无法知道需要应用此装箱,因为我们认为该方法必须适用于任何类型T
,这可能并非总是如此代表Double
。
理论上,您可以更改ArrayList::toArray
的实现,以显式检查数组的组件类型和列表元素类型是否适用于拆箱,但这种方法会导致几个分支会增加相当方法的运行时开销。相反,编写一个专门用于Double
类型的小实用程序方法,并应用由于特化而隐式拆箱。对所有列表项的迭代就足够了,这也是ArrayList::toArray
的实现方式。如果您的数组很小,请考虑使用一组加框值Double[]
而不是double[]
。如果您的阵列很大,使用寿命很长,或者为了符合第三方API而限制为原始类型,请使用该实用程序。另外,如果你想要进行整体拳击,请注意原始集合的实现。使用Java 8,使用Stream
来内联阵列转换。