0

I would need some help optimising the way to iterate through a list of 200 lines. My 1st class is as below

Class Vehicle
 Date date
 int nbOfVehicleArriving


Class Planning
 int date
 int nbOfallowedVehicles

So, I have a list of Vehicles arriving per time ex:

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
....

And I have some agenda

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

I need to calculate the number of vehicles in the queue.

What i'm planning to do is to iterate with the Vehicles and then in it iterate with the Planning.

Is there a better way of doing this??

Thanks in advance

testeurFou
  • 71
  • 3
  • 11
  • 1
    what do you think about using a map with date as key? – jhamon Jun 13 '18 at 09:43
  • If you are looking for optimization, don't use java stream. Do a google search and you'll find lots of articles and comparisons on how slow stream functions are. – Jorge.V Jun 13 '18 at 09:45
  • 4
    @Jorge.V generalization by saying "Streams are slow, do not use them" is definitely not correct. It's a matter of the use-case. – Ben Jun 13 '18 at 09:48
  • @Ben I disagree. There is not a single case where Streams are not much slower. At most they come close to imperative. See [link](https://stackoverflow.com/questions/22658322/java-8-performance-of-streams-vs-collections) – Jorge.V Jun 13 '18 at 09:51
  • 1
    For 200 lines of input speed probably does not even matter. Expressiveness is most often more important. – xtofl Jun 13 '18 at 09:54
  • Thanx for your concerns. I will look into your links and try to get an opinion.. – testeurFou Jun 13 '18 at 11:34

3 Answers3

0

You may try this out.

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())));
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • I think my question was not enough clear. I to get the sum of each mins. not the whole sum.. So for each timestamp of Vehicle, I can count the number of vehicules left in the queue – testeurFou Jun 13 '18 at 11:35
  • What you need to get exactly? – Ravindra Ranwala Jun 13 '18 at 11:36
  • 01/01/2018 00:00:00 12 -3 = 9 vehicules in the queue 01/01/2018 00:10:00 10- 2 = 8 vehicules in the queue 01/01/2018 01:00:00 5 - 3 = 2 vehicules in the queue 01/01/2018 01:10:00 10- 5 = 5 vehicules in the queue – testeurFou Jun 13 '18 at 11:39
  • Hi, thanks for your help. But I am having issues when the 2 lists are not of the same size. Also, I need to add the cumulated number of vehicles left. https://pastebin.com/print/rka0FND8 – testeurFou Jun 15 '18 at 13:19
0

You could also use flatMap to merge the two arrays together and then simply extract the counts (this would involve casting) and sum these up.

Here is a full working example demonstrating how you can use 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;
    }
}

If you run this example it will output 38 on the console.

gil.fernandes
  • 12,978
  • 5
  • 63
  • 76
0

For 200 lines it probably doesn't make any difference what solution you choose. But if you want a solution which scales to a very long list the correct approach is to zip the two lists (or streams) together (this way you avoid looping twice), and use a function to produce the combined result. Guava itself provides a zip() method, but you can also write your own.

Not sure what you mean by 'number of vehicles in the queue', but I am going to assume that you want to know how many were left in the end that have not been allowed in yet.

You can create your own class which maps the vehicles arriving with the agenda for that date.

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

Once you have this you can easily do a reduce() operation to carry forward any vehicles left over from the previous slot.

So something like this (using the Guava Streams class):

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

UPDATE:

Seems that the queue is per time slot. In that case you might want to have a special class like this, which stores the queue size per slot:

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

Then get a stream of these classes like this:

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

This way you have a list of queued vehicles for each date. As a side note, I would use the Java 8 LocalDateTime not the old Date class.

jbx
  • 21,365
  • 18
  • 90
  • 144
  • 01/01/2018 00:00:00 12 -3 = 9 vehicules in the queue 01/01/2018 00:10:00 10- 2 = 8 vehicules in the queue 01/01/2018 01:00:00 5 - 3 = 2 vehicules in the queue 01/01/2018 01:10:00 10- 5 = 5 vehicules in the queue – – testeurFou Jun 13 '18 at 11:42
  • Updated the answer to include a separate queue size for each timeslot too – jbx Jun 13 '18 at 11:59
  • Hi, thanks for your help. But I am having issues when the 2 lists are not of the same size. Also, I need to add the cumulated number of vehicles left. pastebin.com/print/rka0FND8 – testeurFou Jun 15 '18 at 13:20
  • Well you didn't describe any of these requirements in your question. Ask a new question and include the proper details, with an example output of what you want *in the question* (that link doesn't work) – jbx Jun 18 '18 at 05:39
  • Thanks for your help, I was thinking more of you can help me begin, and then I try myself.. so that I don't feel like assisted.. But, you guys rock!! – testeurFou Jun 18 '18 at 06:22
  • Well there are multiple ways to do it of course. If you created a new question with details link to it here so that I can have a look. Try to describe the case in detail (like how the 2 lists not same size is different, is it missing time slots? is it the same just shorter?) with examples of the lists, and what you are expecting. – jbx Jun 18 '18 at 14:09