Как отфильтровать массив в Java? - PullRequest
16 голосов
/ 17 января 2010

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

11 голосов
/ 17 января 2010

РЕДАКТИРОВАТЬ: увидел, что ArrayList не в J2ME, но на основе документации, он имеет вектор. Если этот класс Vector отличается от вектора J2SE (как в этой документации указано ), возможно, будет работать следующий код:

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);
5 голосов
/ 18 января 2010

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

2 голосов
/ 17 января 2010

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

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

1 голос
/ 17 января 2010

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

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

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

1 голос
/ 17 января 2010

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

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

1 голос
/ 17 января 2010

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

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

1 голос
/ 17 января 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...