Как фильтровать массив в Java?

как я могу фильтровать массив в Java?

у меня есть массив объектов, например автомобилей:

класс:

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

использование:

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

теперь я хочу фильтровать массив автомобилей, сохраняя только 4 двери и более:

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

как я должен это сделать?

прежде чем я сделал это с вектором:

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

и тогда я бы сделал новый массив с размером вектора. Затем я снова перебирал вектор и заполнить новый массив. Я знаю, что это очень большая процедура-то простая.

я использую J2ME.

7 ответов


EDIT: увидел, что ArrayList не находится в J2ME, но на основе документации он имеет вектор. Если этот векторный класс отличается от вектора J2SE (as в этой документации указано), тогда, возможно, будет работать следующий код:

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

самый эффективный способ сделать это-если предикат, который вы фильтруете, является недорогим, и вы обращаетесь к нему с помощью одного потока-обычно пересекать список дважды:

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

это дважды пересекает список и дважды вызывает тест, но не имеет дополнительных выделений или копирования. Методы векторного стиля пересекают список один раз, но выделяют примерно в два раза больше памяти (временно) и копирует каждый хороший элемент примерно в два раза. Так что если вы фильтруете крошечный часть списка (или производительность не проблема, что очень часто не так), то векторный метод хорош. В противном случае, версия выше работает лучше.


Если вам действительно нужен простой массив в результате, я думаю, что ваш путь-это путь: вы не знаете количество результирующих элементов перед фильтрованием, и вы не можете построить новый массив, не зная количества элементов.

однако, если вам не нужна потокобезопасность, рассмотрите возможность использования ArrayList вместо Vector. Это должно быть немного быстрее. Затем использовать ArrayList и Л!--2-- > метод для получения массива.


Я не вижу много ошибок в вашем коде. Вы могли бы просто придерживаться векторов во всем, хотя.

вы можете упростить вторую часть (где вы копируете соответствующие элементы в новый массив) с помощью Vector.copyInto (Object []).


нет прямого способа удалить элементы из массива; его размер фиксирован. Что бы вы ни делали, вам нужно каким-то образом выделить новый массив.

Если вы хотите избежать незначительных накладных расходов памяти при выделении Vector, другой вариант - сделать два прохода по вашему массиву. В первый раз, просто подсчитать количество элементов, которые вы хотите сохранить. Затем выделите массив такого размера и повторите цикл над старым массивом, копируя соответствующие элементы в новый массив.


можно использовать System.arrayCopy():

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

обновление: System.arrayCopy доступна Ява меня с API, в отличие от вектора.подсписок.)( Спасибо за поправку.


вам все равно нужно будет создать новый массив.

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

это не совсем эффективно, хотя.