I allocate a large array of doubles as
double[] x = new double[ n ];
where n is large, and I want to avoid initialization to save time. Is it possible?
Declaring an array does not initialize it. In order to store values in the array, we must initialize it first, the syntax of which is as follows: datatype [ ] arrayName = new datatype [size];
Macros: For initializing a huge array with the same value we can use macros. Using For Loop: We can also use for loop to initialize an array with the same value.
The initializer for an array is a comma-separated list of constant expressions enclosed in braces ( { } ). The initializer is preceded by an equal sign ( = ). You do not need to initialize all elements in an array.
Array Initialization in Java To use the array, we can initialize it with the new keyword, followed by the data type of our array, and rectangular brackets containing its size: int[] intArray = new int[10]; This allocates the memory for an array of size 10 .
Short answer: No. Arrays always get zeroed out when they are created.
If your profiling has shown this to be a major bottleneck, you could consider keeping a pool of array instances, with the length of each set to bigger than n
will ever be. The problem would be that you then probably need a wrapper object to contain the data array and the actual length that is used, since you can no longer use data.length
.
** WARNING ** UNSAFE ALTERNATIVE **
It's not an exact solution, but it could be a viable alternative. This method has some risks. But you might go this route if it's really absolutely necessary. This method is using an undocumented sun.misc.Unsafe
class to allocate off-heap memory to store the double values. Off-heap meaning it's not garbage-collected, so you'll need to take care to deallocate the associated memory.
The following code is based on this blog post about sun.misc.Unsafe.
import java.lang.reflect.Field;
import sun.misc.Unsafe;
@SuppressWarnings("restriction")
public class SuperDoubleArray {
private final static Unsafe unsafe = getUnsafe();
private final static int INDEX_SCALE = 8;
private long size;
private long address;
public SuperDoubleArray(long size) {
this.size = size;
address = unsafe.allocateMemory(size * INDEX_SCALE);
}
private static Unsafe getUnsafe() {
try {
Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
singleoneInstanceField.setAccessible(true);
return (Unsafe) singleoneInstanceField.get(null);
} catch (IllegalArgumentException | SecurityException
| NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void set(long i, double value) {
unsafe.putDouble(address + i * INDEX_SCALE, value);
}
public double get(long idx) {
return unsafe.getDouble(address + idx * INDEX_SCALE);
}
public long size() {
return size;
}
public void deallocate() {
unsafe.freeMemory(address);
}
}
The following code will print some random double values coming from the unitialized memory.
SuperDoubleArray sda = new SuperDoubleArray(100);
for (int i=0; i<sda.size(); i++) {
System.out.println(sda.get(i));
}
sda.deallocate();
There are no safety/range-checks, no nothing, you can easily crash the JVM with it, might not work with non-SUN JREs, might even stop working in future SUN JRE versions, but it might be the only solution in some cases. It can also allocate > Integer.MAX_VALUE
sized pseudoarrays, unlike Java arrays.
java.nio.ByteBuffer.allocateDirect(...)
actually uses the same Unsafe class behind the scenes to allocate byte buffers, and you could use ByteBuffer.allocateDirect(8*size).asDoubleBuffer()
to adapt it to a DoubleBuffer
, but ByteBuffer.allocateDirect(...)
is still initializing the buffer with zeroes, so it might have a performance overhead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With