If are open to using a third party library, you might consider using an immutable primitive collection, even if you don't need concurrency. It will be almost as memory efficient and performant as a primitive array. You can build up the data using a mutable data structure at application start up, and then convert it to an immutable data structure once all the data is loaded. Eclipse Collections has a set of mutable and immutable primitive data structures that can be used. Here is an example showing up to build up a mutable list of 10K random doubles, and then converting the MutableDoubleList to an ImmutableDoubleList. This will have the effect of trimming the collection as well as making it immutable.
Random random = new Random();
MutableDoubleList list =
random.doubles(10000, 0.0, 100.0)
.collect(
DoubleLists.mutable::empty,
MutableDoubleList::add,
MutableDoubleList::addAll);
ImmutableDoubleList immutableDoubleList = list.toImmutable();
Assert.assertEquals(10000, immutableDoubleList.size());
System.out.println(immutableDoubleList.count(d -> d > 80.0d));
System.out.println(immutableDoubleList.get(0));
System.out.println(immutableDoubleList.get(99));
System.out.println(immutableDoubleList.get(999));
System.out.println(immutableDoubleList.get(9999));
I've seen this pattern used quite often with Eclipse Collections. The same pattern (mutable build at startup -> immutable) can be used with both object and primitive collections.
Note: I am a committer for Eclipse Collections.