开发者

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 > 开发者_C百科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.


I can't see much wrong with your code. You could just stick with Vectors throughout though.

You could simplify the second part (where you copy the matching items into the new array) using Vector.copyInto(Object[]).


There's no direct way to remove elements from an array; its size is fixed. Whatever you do, you need to allocate a new array somehow.

If you want to avoid the minor memory overhead of allocating a Vector, another option would be to make two passes over your array. The first time, simply count the number of elements that you want to keep. Then allocate an array that size, and loop over your old array again, copying matching elements into the new array.


You can use System.arrayCopy():

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

UPDATE: System.arrayCopy is available in Java ME API, unlike Vector.subList(). Thanks for the correction.


You will need to create a new array anyway.

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

This isn't quite efficient, though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜