Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to filter an array in Java?

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.

like image 547
hsmit Avatar asked Jan 17 '10 20:01

hsmit


3 Answers

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);
like image 68
Kaleb Brasee Avatar answered Oct 12 '22 09:10

Kaleb Brasee


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.

like image 32
Rex Kerr Avatar answered Oct 12 '22 10:10

Rex Kerr


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.

like image 2
Joonas Pulakka Avatar answered Oct 12 '22 11:10

Joonas Pulakka