2010-11-15 12 views
9

Soy un principiante con Java.Java: la mejor forma de implementar una matriz de objetos de tamaño dinámico

Tengo que implementar una matriz de objetos que cambia de tamaño durante la ejecución.

El código que estoy escribiendo va a ser portado en Android también.

De acuerdo con su experiencia, ¿cuál es la mejor clase para implementar eso?

Gracias,
Dan

+2

Eso es difícil de responder sin conocer los requisitos. Eche un vistazo a http://download.oracle.com/javase/tutorial/collections/index.html y vea cuál encaja en la factura. –

+0

¿Por qué no usar los que están en la API, ArrayList por ejemplo? – dacwe

Respuesta

21

Java tiene una capacidad de plantilla inadecuada. Mientras desee una matriz de objetos, entonces ArrayList<T> es bueno. Para los primitivos, es horrible.

Suponiendo que haya una jerarquía de objetos que desea poner en una lista, ArrayList es ideal:

ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>(); 

vehicles.add(new Car(...)); 
vehicles.add(new Truck(...)); 

Asumo en el ejemplo anterior que vehículo es la clase base, y coches y camiones son subclases.

Por otro lado, si desea una lista de números, Java es muy ineficiente. Cada objeto es una referencia (realmente un puntero de 4 bytes) a un fragmento de memoria de 12 bytes, más lo que realmente está usando. Como ArrayList no puede aplicarse a int, esto significa que crear una lista de números significa:

  1. Creación de una lista de Entero, el contenedor de objetos para int.
  2. Convirtiendo los objetos cada vez que saca un número. Esto se hace automáticamente en estos días, pero lleva tiempo.
  3. Inicializando 5 veces más almacenamiento que el necesario.

Por lo tanto, si está manipulando grandes trozos de datos primitivos (int, float, double), puede valer la pena escribir su propia versión de ArrayList. Esto es particularmente importante cuando los datos son grandes y la plataforma es pequeña (como una cosa portátil de Android).

Compare esto:

ArrayList<Integer> list = new ArrayList<Integer>(); 
for (int i = 0; i < 1000000; i++) 
    list.add(i): 

a:

public class IntArray { 
private int[] data; 
private int used; 
private void grow() { 
// implement code to make data double in size here... 
} 
public IntArray(int size) { 
    data = new int[size]; 
    used = 0; 
} 

public void add(int i) { 
    if (i >= data.length) grow(); 
    data[used++] = i; 
} 
} 

IntArray list2 = new IntArray(1000000); 
for (int i = 0; i < 1000000; i++) 
    list2.add(i); 

La última vez que Benchmarked ella, el uso óptimo de la lista primitiva es más de 10 veces más rápido que el uso ciertamente subóptima de ArrayList . Para ser más justos, preasignar el arraylist para que tenga el tamaño correcto, aún es mucho más lento.

LinkedList solo vale la pena si está insertando al principio o al medio de una lista. Si su lista se está compilando al agregarla al final, ArrayList dominará completamente LinkedList. Entonces, para una lista típica de objetos que está construyendo en orden, ArrayList es lo que está buscando. Para obtener una gran lista de elementos primitivos como int o double, escriba su propia lista.

+0

Mientras que los usos donde una 'LinkedList' es mejor pueden ser raros en comparación con 'ArrayList', existen y' LinkedList' puede funcionar _significativamente_ mejor en ellos. El uso en cola de una lista es un ejemplo ... eliminar del frente de una 'ArrayList' es extremadamente caro en comparación con' LinkedList'. Ver [esto] (http://blog.publicobject.com/2010/07/caliper-confirms-reality-linkedlist-vs.html) y [esto] (http://microbenchmarks.appspot.com/run/[email protected] gmail.com/com.publicobject.blog.ListAsQueueBenchmark). – ColinD

+0

@Colin, usar una lista de matrices ingenuamente en lugar de una lista enlazada puede ser algo malo. Pero si desea una cola más rápida, apostaría a que la implementación de una cola circular con una cabecera/cola especificada vencerá a LinkedList por un amplio margen, incluso si puede hacer que crezca cuando/si lo necesita, el caso promedio será solo colocar objetos dentro de una lista ya existente. Sí, insertar al principio de una ArrayList es costoso. – Dov

2

Usted debe conocer a su auto con la collection framework en Java. Tienes cosas como Set, List, Map, SortedSets, etc ... que pueden ser estructuras de datos realmente útiles.

0

Depende de para qué lo va a usar.

Si tiene una matriz que cambia de tamaño con frecuencia, entonces le recomiendo usar un ArrayList o algo más de la collection framework (dependiendo de lo que vas a utilizarlo para).

Si sin embargo tiene una matriz que cambia de tamaño con muy poca frecuencia, pero se lee frecuentemente, probablemente sería más rápido utilizar una matriz regular y luego cambiar su tamaño cuando sea necesario en lugar

Arrays.copyOf(array, newSize); 

espero que ayude! :)

+0

Si bien las matrices primitivas son mejores a veces, no hay realmente ninguna buena razón para usar una matriz de objetos en Java. "probablemente sería más rápido" ... optimización prematura. – ColinD

+0

El uso de una clase primitiva es diferente a la escritura con matrices codificadas. Y se presta demasiada atención a evitar la "optimización prematura" en lugar de simplemente saber lo que es eficiente y hacerlo de forma rutinaria. Es tan fácil escribir un buen código en la mayoría de los casos como un código incorrecto. A veces, lleva un poco más de trabajo, y es entonces cuando puedes pensar en hacerlo más tarde. – Dov

+0

@Dov: Ciertamente estoy de acuerdo en que cuando se trata de hacer algo claramente inferior en lugar de hacer algo que es correcto y que probablemente rinda mejor por el mismo esfuerzo, no es una optimización prematura hacer lo correcto. Pero las matrices son inferiores a las listas en una gran cantidad de formas y usarlas directamente seguramente creará más trabajo para hacer cosas simples y hará que el código sea más difícil de entender, y probablemente no transmita ninguna mejora de rendimiento que importe para todos, pero el más bajo -level de código. Es por eso que consideraría esta optimización prematura. – ColinD

Cuestiones relacionadas