Как фильтровать массив в 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:

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

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

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

Ответы

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

Однако, если вам не нужна безопасность потоков, используйте ArrayList вместо Vector. Это должно быть несколько быстрее. Затем используйте метод ArrayList toArray для получения массива.

Ответ 4

Вы можете использовать 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 доступен в Java ME API, в отличие от Vector.subList(). Спасибо за исправление.

Ответ 5

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

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

Ответ 6

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

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

Ответ 7

В любом случае вам нужно будет создать новый массив.

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

Это не совсем эффективно.