Как отфильтровать множество на Яве?

Как я могу отфильтровать множество на Яве?

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

Класс:

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.

18
задан Peter Mortensen 17 January 2010 в 22:08
поделиться

7 ответов

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

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

-121--2325130-

Редактировать: Увидел, что 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);
12
ответ дан 30 November 2019 в 08:43
поделиться

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

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

1
ответ дан 30 November 2019 в 08:43
поделиться

Для передачи данных между различными экземплярами приложения можно использовать Pipes . Если вам просто нужно сообщить другому экземпляру, что что-то произошло, вы можете отправить сообщения из одного приложения в другое с помощью API SendMessage.

-121--2387536-

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

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

-121--2325131-

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

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

2
ответ дан 30 November 2019 в 08:43
поделиться

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

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
ответ дан 30 November 2019 в 08:43
поделиться

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

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 хорош. В противном случае, вышеприведенная версия работает лучше.

5
ответ дан 30 November 2019 в 08:43
поделиться

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

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

1
ответ дан 30 November 2019 в 08:43
поделиться

Вы можете использовать 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(). Спасибо за исправление.

1
ответ дан 30 November 2019 в 08:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: