2010-01-17 14 views
15

¿Cómo puedo filtrar una matriz en Java?¿Cómo se filtra una matriz en Java?

Tengo una gran variedad de objetos, por ejemplo los coches:

Clase:

public class Car{ 
    public int doors; 
    public Car(int d){ 
     this.doors = d; 
    } 
} 

Uso:

Car [] cars = new Cars[4]; 
cars[0] = new Car(3); 
cars[1] = new Car(2); 
cars[2] = new Car(4); 
cars[3] = new Car(6); 

Ahora quiero filtrar el conjunto de vehículos, manteniendo sólo 4 puertas y más:

for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     //add cars[i] to a new array 
    } 
} 

¿Cómo debo hacer esto?

Antes lo hacía con un vector:

Vector subset = new Vector(); 
for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     //add cars[i] to a new array 
     subset.addElement(cars[i]); 
    } 
} 

Y entonces me gustaría hacer una nueva matriz con el tamaño del vector. Luego volvería a recorrer el vector y llenaría la nueva matriz. Sé que este es un procedimiento muy grande para algo simple.

Estoy usando J2ME.

+1

¿Es realmente tan importante que sus contenedores sean matrices y no vectores? Porque los vectores suenan como lo correcto para usar. – zneak

+1

Bueno, no puedo usar automóviles Vector en mi entorno. Así que tengo que hacer moldes todo el tiempo, lo cual puede ser difícil ... – hsmit

Respuesta

10

EDIT: vio que ArrayList no está en J2ME, pero según la documentación, tiene un Vector. Si esa clase Vector es diferente de J2SE vectorial (como this documentation indicates), entonces tal vez el siguiente código funciona:

Vector carList = new Vector(); 
for(int i = 0; i<cars.length; i++){ 
    if(cars[i].doors > 4) 
     carList.addElement(cars[i]); 
    } 
} 
Car[] carArray = new Car[carList.size()]; 
carList.copyInto(carArray); 
+0

carList.toArray() no funciona en J2ME, ¡gracias por su ayuda de todos modos! – hsmit

+0

No me di cuenta de que Vector se comporta de manera diferente, tal vez intente con la segunda parte del código que agregué. –

+0

es posible que desee inicializar el vector con cars.length. quizás sería más efectivo. – Bozho

1

Puede utilizar System.arrayCopy():

Car[] cars = ... 
int length = cars.length < 4 ? cars.length() : 4; 
Car filter = new Car[4]; 
System.arrayCopy(cars, 0, filter, 0, length); 

ACTUALIZACIÓN: System.arrayCopy está disponible en Java ME API, a diferencia de Vector.subList(). Gracias por la corrección.

+0

No creo que pueda usarlos en J2ME ... – hsmit

+0

@hsmit, System.arrayCopy() están disponibles en Java ME, pero no ' Vector.subList() '. – notnoop

1

No puedo ver mucho mal con su código. Sin embargo, podrías simplemente quedarte con los vectores.

Puede simplificar la segunda parte (donde copia los elementos coincidentes en la nueva matriz) utilizando Vector.copyInto (Object []).

2

Si realmente necesita una matriz simple como resultado, creo que su camino es el camino a seguir: no sabe la cantidad de elementos resultantes antes de filtrar, y no puede construir una nueva matriz sin saber la cantidad de elementos

Sin embargo, si no necesita seguridad de subprocesos, considere usar ArrayList en lugar de Vector. Debería ser algo más rápido. Luego use el método toArray de ArrayList para obtener la matriz.

+0

Creo que ArrayList no se usa en J2ME desafortunadamente ... – hsmit

+0

Ah, buen punto. Así que esto se reduce a una elección entre el uso de la memoria y la velocidad: cree un Vector intermedio y obtenga el conjunto de ese (que es rápido pero toma la memoria), o recorra la lista dos veces, la primera vez solo para averiguar el número de elementos, y la segunda vez para llenar un conjunto de ese tamaño (que es probablemente más lento, pero produce menos basura). –

+1

No use una ArrayList, use una LinkedList si no conoce la cantidad de elementos de antemano. Agregar nuevos campos a una ArrayList es más caro que a LinkedList, debido a su estructura interna. –

1

No hay manera directa para eliminar elementos de una matriz; su tamaño es fijo. Hagas lo que hagas, necesitas asignar una nueva matriz de alguna manera.

Si desea evitar la sobrecarga de memoria menor de asignar un Vector, otra opción sería hacer dos pasadas sobre su matriz. La primera vez, simplemente cuente la cantidad de elementos que desea conservar. A continuación, asigne una matriz de ese tamaño y vuelva a recorrer su matriz anterior, copiando elementos coincidentes en la nueva matriz.

+0

Sí, eso suena interesante. ¿Tienes alguna idea sobre el rendimiento de ambos? – hsmit

+0

Me gustaría * adivinar * que mi enfoque podría ser más rápido, dependiendo de lo caro que es crecer un vector en comparación con los ciclos de bucle adicionales involucrados. Pero no sé mucho sobre las características de rendimiento de J2ME, y también dependerá de qué tan grandes sean sus matrices, etc. Tendría que hacer un benchmark para estar seguro. – Porculus

1

Tendrá que crear una nueva matriz de todos modos.

Vector vector = new Vector(array.length); 

for (int i = 0; i < array.length; i++) { 
    if (array[i].doors > 4) { 
     vector.add(array[i]); 
    } 
} 

Car[] result = new Car[vector.size()]; 
vector.copyInto(result); 

Esto no es muy eficiente, sin embargo.

+0

No hay 'java.util.Iterator' en Java ME: http://java.sun.com/javame/reference/apis/jsr139/ – BalusC

+0

woops :) cómo es que lo he olvidado. (Actualizado) – Bozho

5

La forma más eficiente de hacer esto - si el predicado que está filtrando en es de bajo costo y que está accediendo a ella con un solo hilo - es por lo general para recorrer la lista dos veces:

public Car[] getFourDoors(Car[] all_cars) { 
    int n = 0; 
    for (Car c : all_cars) if (c.doorCount()==4) n++; 
    Car[] cars_4d = new Car[n]; 
    n = 0; 
    for (Car c : all_cars) if (c.doorCount()==4) cars_4d[n++] = c; 
    return cars_4d; 
} 

Esto atraviesa la lista dos veces y llama a la prueba dos veces, pero no tiene asignaciones adicionales ni copia. Los métodos de estilo vectorial atraviesan la lista una vez, pero asignan aproximadamente el doble de la memoria que necesita (transitoriamente) y copia cada elemento bueno aproximadamente dos veces. Entonces, si está filtrando una pequeña fracción de la lista (o el rendimiento no es un problema, que a menudo no lo es), entonces el método Vector es bueno. De lo contrario, la versión anterior funciona mejor.

Cuestiones relacionadas