这两者的主要区别是什么:
val array: Array<Double> = arrayOf()
与
val array: DoubleArray = doubleArrayOf()
我知道一个使用原始数据类型double
第二个基于对象的countrepartDouble
。
使用普通DoubleArray
是否有任何惩罚或不利因素?
为什么我想知道:
我正在使用 JNI,为了Double
,我必须打电话
jclass doubleClass = env->FindClass("java/lang/Double");
jmethodID doubleCtor = env->GetMethodID(doubleClass, "<init>", "(D)V");
jobjectArray res = env->NewObjectArray(elementCount, doubleClass, nullptr);
for (int i = 0; i < elementCount; i++){
jobject javaDouble = env->NewObject(doubleClass, doubleCtor, array[i]);
env->SetObjectArrayElement(res, i, javaDouble);
env->DeleteLocalRef(javaDouble);
}
与
jdoubleArray res = env->NewDoubleArray(elementCount);
env->SetDoubleArrayRegion(res, 0, elementCount, array);
没有惩罚(事实上,由于没有装箱,它会更快),但是,与 Java 中的原始类型一样,如果您希望能够将它们与[Int/Double/etc]Array
一起使用,它会迫使您创建某些方法的专用重载。
这实际上已经在 Kotlin 论坛上讨论过了:
整数数组的内存布局与对象指针数组的内存布局完全不同。
Norswap在那次讨论中的评论很好地总结了这种权衡:
本机的 [
int[]
/IntArray
] 读/写更快,但包装的 [Integer[]
/Array<Int>
] 不需要每次跨越泛型边界时都完全转换。
#7, 诺斯瓦普
例如,接受Array<Int>
(在 JVM 上Integer[]
)的函数将不接受IntArray
(int[]
)。
您已经列出了唯一真正的区别,一个被编译为原始double[]
,另一个被编译为Double[]
。但是,Double[]
是一个对象数组,因此每当通过将值设置为double
来修改数组或检索double
时,将分别执行装箱和取消装箱。
出于速度和内存原因,通常建议改用DoubleArray
。
作为由于对象包装器而导致的速度惩罚的示例,请看一下这篇文章的开头,摘自Effective Java:
public static void main(String[] args) {
Long sum = 0L; // uses Long, not long
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
将Long
替换为long
可将运行时间从 43 秒缩短到 8 秒。