library joiner google cache java data-structures guava

java - joiner - Lista<Double> que usa RAM de doble[]?



guava preconditions (6)

Los expertos en Java enfatizan la importancia de evitar la optimización prematura y, en cambio, enfocarse en el diseño limpio de OO. Estoy tratando de conciliar este principio en el contexto de reescribir un programa que usa una gran variedad de elementos largos (unos pocos millones). Parece que usar un ArrayList consumiría aproximadamente 3 veces la memoria de una matriz primitiva de longevos, y perder esa RAM me parece una preocupación legítima.

Estoy basando esto en un experimento que hice usando la clase MemoryTestBench que se describe aquí . Mi prueba y salida son las siguientes:

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); } }

y salida:

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

Mi pregunta es: ¿Cómo puedo obtener los beneficios de una lista OO y aún conservar la pequeña huella de memoria de una matriz primitiva? Creo que la guayaba podría proporcionar la respuesta, pero al analizar la API no es obvio qué clase usar en lugar de ArrayList.

Gracias por cualquier sugerencia.


Creo que estás buscando FastUtil''s DoubleArrayList , está respaldado por una matriz primitiva.

Si su colección es REALMENTE grande (más grande que 2 ^ 31 elementos) también puede mirar sus BigArrays



Es una buena pregunta: rendimiento frente a la limpieza del código. Creo que tiene motivos para preocuparse menos por el diseño limpio de OO y simplemente centrarse en crear una buena solución al problema específico de trabajar con una gran variedad de largos. Si lo hace, mantener el código orientado al rendimiento en una clase / paquete minimizará su impacto en el diseño general. Supuestamente, administrar la gran lista de largos es solo una pequeña parte de una aplicación más grande ...


Escriba su propia implementación de ArrayList que utiliza una matriz de primitivos. Copie el código ArrayList actual y reemplace el Objeto interno [] con un doble [].

Debe ser una copia hacia adelante bastante recta y reemplazar.

EDITAR: Mayor peligro para el consumo de memoria va a ser el "crecer". Tomará brevemente por lo menos el doble del espacio, más el espacio adicional que usted crezca. Si no puede pre-dimensionar la matriz para evitar esto, es posible que desee considerar una implementación ligeramente diferente que use múltiples matrices a medida que crece con el tiempo. Un poco más de matemáticas al insertar e indexar, pero no debería ser demasiado malo.


Podría considerar usar Trove , que proporciona soporte para colecciones primitivas, por ejemplo, la clase TDoubleArrayList :

Una lista redimensionable, respaldada por una matriz de dobles primitivas.

Edición: es cierto que esta clase no implementa la List , pero ese es el precio de Java de evitar los primitivos en caja. La solución de Guava es la más versátil, mientras que Trove es la mejor para requisitos de rendimiento más extremos.


Arrays.asList(T...) puede ser lo que estás buscando. Devuelve una instancia de la List<T> respaldada por la matriz que se le pasó.