Как фильтровать массив в 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);
Это не совсем эффективно.