Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<Double> that uses RAM of double[]?

Java experts emphasize the importance of avoiding premature optimization, and focusing instead on clean OO design. I am trying to reconcile this principle in the context of rewriting a program that uses a large array of long elements (a few million). It seems that using an ArrayList would consume about 3x the memory of a primitive array of longs, and wasting that much RAM seems like a legitimate concern to me.

I am basing this off an experiment I did using MemoryTestBench class described here. My test and output are as follows:

package memory;

import java.util.ArrayList;
import java.util.List;

public class ArrayListExperiment {

public static void main(String[] args) {

    ObjectFactory arrayList = new ObjectFactory() {
        public Object makeObject() {
            List<Long> temp = new ArrayList<Long>(1000);
            for (long i=0; i<1000; i++)
                temp.add(i);
            return temp;
        }
    };

    ObjectFactory primitiveArray = new ObjectFactory() {
        public Object makeObject() {
            long[] temp = new long[1000];
            for (int i=0; i<1000; i++)
                temp[i] = i;
            return temp;
        }
    };

    MemoryTestBench memoryTester = new MemoryTestBench();
    memoryTester.showMemoryUsage(primitiveArray);
    memoryTester.showMemoryUsage(arrayList);
}
}

and output:

memory.ArrayListExperiment$2 produced [J which took 8016 bytes
memory.ArrayListExperiment$1 produced java.util.ArrayList which took 24968 bytes

My question is: How can I reap the benefits of an OO List and still retain the small memory footprint of a primitive array? I think guava might provide the answer, but glancing through the API it's not obvious to me which class to use in place of ArrayList.

Thanks for any suggestions.

like image 681
Jonah Avatar asked Dec 21 '11 06:12

Jonah


3 Answers

I think what you looking for in Guava is Doubles.asList

like image 110
sanjary Avatar answered Oct 29 '22 23:10

sanjary


You might consider using Trove, which provides support for primitive collections, for example the TDoubleArrayList class:

A resizable, array-backed list of double primitives.

Edit: It's true that this class doesn't implement List, but that's Java's price of avoiding boxed primitives. Guava's solution is the most versatile, while Trove is best for more extreme performance requirements.

like image 22
Paul Bellora Avatar answered Oct 30 '22 01:10

Paul Bellora


I think you are looking for FastUtil's DoubleArrayList - it's backed by a primitive array.

If your collection is REALLY big (larger than 2^31 elements) you may also want to look at their BigArrays

like image 37
Timothy Jones Avatar answered Oct 29 '22 23:10

Timothy Jones