Цикл внутри нескольких массивов в Java Stream - PullRequest
0 голосов
/ 13 июня 2018

Мне понадобится помощь в оптимизации способа перебора списка из 200 строк.Мой 1-й класс, как показано ниже

Class Vehicle
 Date date
 int nbOfVehicleArriving


Class Planning
 int date
 int nbOfallowedVehicles

Итак, у меня есть список транспортных средств, прибывающих за время, например:

01/01/2018 00:00:00 12
01/01/2018 00:10:00 10
01/01/2018 01:00:00 5
01/01/2018 01:10:00 10
....

И у меня есть некоторые планы

01/01/2018 00:00:00 3
01/01/2018 00:10:00 2
01/01/2018 01:00:00 3
01/01/2018 01:10:00 5

Мне нужно рассчитать количество автомобилей в очереди.

Что я планирую сделать, это выполнить итерацию с Транспортными средствами, а затем выполнить итерацию с Планированием.

Есть лилучший способ сделать это ??

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Вы также можете использовать flatMap, чтобы объединить два массива, а затем просто извлечь счетчики (это может привести к приведению) и суммировать их.

Вот полный рабочий пример, демонстрирующий, как вы можете использоватьflatMap:

import java.util.Arrays;
import java.util.Date;
import java.util.stream.Stream;

public class MergeStreams {

    public static void main(String[] args) {
        Vehicle[] vehicles = {new Vehicle(new Date(), 10), new Vehicle(new Date(), 11)};
        Planning[] plannings = {new Planning(new Date(), 5), new Planning(new Date(), 12)};
        int sum = Stream.of(vehicles, plannings)
            .flatMap(Arrays::stream)
            .map(object -> object instanceof Vehicle ? ((Vehicle) object).getNbOfVehicleArriving() : ((Planning) object).getNbOfallowedVehicles())
            .mapToInt(Integer::intValue)
            .sum();
        System.out.println(sum);
    }
}

class Vehicle {
    private Date date;
    private int nbOfVehicleArriving;

    public Vehicle(Date date, int nbOfVehicleArriving) {
        this.date = date;
        this.nbOfVehicleArriving = nbOfVehicleArriving;
    }

    public int getNbOfVehicleArriving() {
        return nbOfVehicleArriving;
    }
}


class Planning {
    private Date date;
    private int nbOfallowedVehicles;

    public Planning(Date date, int nbOfallowedVehicles) {
        this.date = date;
        this.nbOfallowedVehicles = nbOfallowedVehicles;
    }

    public int getNbOfallowedVehicles() {
        return nbOfallowedVehicles;
    }
}

Если вы запустите этот пример, он выведет 38 на консоль.

0 голосов
/ 13 июня 2018

Для 200 строк, вероятно, не имеет значения, какое решение вы выберете.Но если вам нужно решение, которое масштабируется до очень длинного списка, правильным подходом является zip два списка (или потока) вместе (таким образом вы избегаете циклического повторения дважды) и использование функции для получения комбинированного результата.Сам Guava предоставляет метод zip () , но вы также можете написать свой собственный.

Не уверен, что вы подразумеваете под «количеством транспортных средств в очереди», но я собираюсь предположить, что вы хотите знать, сколько осталось в конце, которые еще не были допущены.

Вы можете создать свой собственный класс, который отображает транспортные средства, прибывающие с повесткой дня на эту дату.

public class VehiclePlanningData {

    private final Vehicle vehicle;
    private final Planning planning;

    public  VehiclePlanningData(Vehicle vehicle, Planning planning) {
        this.vehicle = vehicle;
        this.planning = planning;
    }

    public Vehicle getVehicle() {
        return vehicle;
    }

    public Planning getPlanning() {
        return planning;
    }
}

Получив это, вы можете легко выполнить операцию reduce() для переноса любогоавтомобили остались от предыдущего слота.

Итак, что-то вроде этого (с использованием класса потоков Guava):

int queue = Streams.zip(vehicles.stream(), planning.stream(), (v, p) -> new VehiclePlanningData(v, p))
           .reduce(0, (queue, nextSlot) -> 
              queue + (nextSlot.getVehicle().getNbOfVehicleArriving() 
                       - nextSlot.getPlanning().getNbOfallowedVehicles(), 
              (q1, q2) -> q1 + q2);

ОБНОВЛЕНИЕ:

Кажется, что очередь находится на временной интервал.В этом случае вам может понадобиться специальный класс, такой как этот, который хранит размер очереди на слот:

public class TimeslotQueue {
   private final Date date;
   private final int queueSize;

   public VehicleQueue(Date date, int queueSize) {
     this.date = date;
     this.queueSize = queueSize;
   }

   public Date getDate() { 
     return date;
   }

   public int getQueueSize() {
     return queueSize;
   }
 }

Затем получите поток этих классов, например:

    List<TimeslotQueue> queues = Streams.zip(vehicles.stream(), planning.stream(), 
         (v, p) -> new TimeslotQueue(v.getDate(), 
                        v.getNbOfVehicleArriving() - p.getNbOfallowedVehicles()))
         .collect(Collectors.toList());

Таким образом, у вас есть список транспортных средств в очереди на каждую дату.В качестве примечания я бы использовал Java 8 LocalDateTime, а не старый Date класс.

0 голосов
/ 13 июня 2018

Вы можете попробовать это.

Map<Date, Integer> agendasByDate = agendas.stream()
        .collect(Collectors.toMap(Planning::getDate, Planning::getNbOfallowedVehicles));

Map<Date, Integer> vehiclesInQueueByDate = vehicles.stream().collect(Collectors.toMap(Vehicle::getDate,
        v -> v.getNbOfVehicleArriving() - agendasByDate.get(v.getDate())));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...