4

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);
Salem
  • 13,516
  • 4
  • 51
  • 70
Martin Perry
  • 9,232
  • 8
  • 46
  • 114

1 Answers1

5

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.

Salem
  • 13,516
  • 4
  • 51
  • 70