问题
What is the main difference in these two:
val array: Array<Double> = arrayOf()
vs
val array: DoubleArray = doubleArrayOf()
I know that one is using primitive data type double
and the second its object based countrepart Double
.
Is there any penalty or disadvatnage in using plain DoubleArray
?
Why I want to know:
I am using JNI and for Double
, I have to call
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);
}
vs
jdoubleArray res = env->NewDoubleArray(elementCount);
env->SetDoubleArrayRegion(res, 0, elementCount, array);
回答1:
There is no penalty (in fact, it will be faster due to no boxing), but, as with primitive types in Java, it forces you to create specialized overloads of certain methods if you want to be able to use them with [Int/Double/etc]Array
.
This has actually been discussed over at the Kotlin forums:
the memory layout of an array of integers is quite different from that of an array of object pointers.
Norswap's comment in that discussion summarizes the tradeoff quite well:
The native one [
int[]
/IntArray
] is faster to read/write, but the wrapped [Integer[]
/Array<Int>
] does not need to be entirely converted each time it crosses a generic boundary.
#7, norswap
For example, a function accepting Array<Int>
(Integer[]
on the JVM) will not accept an IntArray
(int[]
).
You have already listed the only real difference, that one is compiled to the primitive double[]
and the other to Double[]
. However, Double[]
is an array of objects, so any time you modify the array by setting a value to a double
, or retrieve a double
, boxing and unboxing will be performed, respectively.
It is usually recommended to use DoubleArray
instead, for speed and memory reasons.
As an example of speed penalties due to the object wrappers, take a look at the start of this post, taken from 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);
}
Replacing Long
with long
brings runtime from 43 seconds down to 8 seconds.
来源:https://stackoverflow.com/questions/49391973/kotlin-use-arraydouble-or-doublearray