Kotlin - 使用 Array<Double> 或 DoubleArray



这两者的主要区别是什么:

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 秒。

最新更新