How can I filter an array in Java?
I have an array of objects, for example cars:
Class:
public class Car{
public int doors;
public Car(int d){
this.doors = d;
}
}
Use:
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);
Now I want to filter the array of cars, keeping only 4 doors and more:
for(int i = 0; i<cars.length; i++){
if(cars[i].doors > 4)
//add cars[i] to a new array
}
}
How should I do this?
Before I did it with a 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]);
}
}
And then I would make a new array with the size of the Vector. Then I would loop over the vector again and fill the new array. I know this is a very large procedure for something simple.
I'm using J2ME.
EDIT: saw that ArrayList is not in J2ME, but based on documentation, it does have a Vector. If that Vector class is different than J2SE Vector (as this documentation indicates), then perhaps the following code would work:
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);
The most efficient way to do this--if the predicate you're filtering on is inexpensive and you're accessing it with a single thread--is usually to traverse the list twice:
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;
}
This traverses the list twice and calls the test twice, but has no extra allocations or copying. The Vector-style methods traverse the list once, but allocates about twice the memory it needs (transiently) and copies every good element about twice. So if you are filtering a tiny fraction of the list (or performance isn't an issue, which very often it isn't), then the Vector method is good. Otherwise, the version above performs better.
If you really need a plain array as the result, I think your way is the way to go: you don't know the number of resulting elements before you filter, and you can't construct a new array without knowing the number of elements.
However, if you don't need thread-safety, consider using ArrayList
instead of a Vector
. It ought to be somewhat faster. Then use ArrayList's toArray
method to get the array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With