3

Not particularly sure what's causing this IndexOutOfBoundsException to occur. The code works perfectly find if I hard code all of the addFlightPath() parameters, but as soon as I attempt to use a for loop to populate the flightPaths arrayList an IndexOutOfBoundsException is thrown. I'm probably missing something small but I'm not sure what it could be.

The exception is thrown on the call to flightPaths.add(path) within the addFlightPath method

public class DijkstrasController
{
    private FlightDatabase flightDatabase;
    private List<Vertex> nodes;
    private List<Edge> flightPaths;

    public DijkstrasController(FlightDatabase flightDatabase)
    {
        this.flightDatabase = flightDatabase;
        populateDijkstrasGraph(flightDatabase);
    }

    public String[] runDijkstras(String sourceAirport, String destinationAirport)
    {
        //Removed for visibility
    }

    public void populateDijkstrasGraph(FlightDatabase fdb)
    {
        nodes = new ArrayList<Vertex>();
        flightPaths = new ArrayList<Edge>();
        for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);

         //This block of code throws an IndexOutOfBounds error
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }

// Uncommenting this section of code allows the program to function normally
//      addFlightPath("Path_AB", 0, 1, 800);
//      addFlightPath("Path_BC", 1, 2, 900);
//      addFlightPath("Path_CD", 2, 3, 400);
//      addFlightPath("Path_BF", 1, 5, 400);
//      addFlightPath("Path_DE", 3, 4, 300);
//      addFlightPath("Path_EB", 4, 1, 600);
//      addFlightPath("Path_CE", 2, 4, 200);
//      addFlightPath("Path_DC", 3, 2, 700);
//      addFlightPath("Path_EB", 4, 1, 500);
//      addFlightPath("Path_FD", 5, 3, 200);
//      addFlightPath("Path_DE", 3, 4, 400);
//      addFlightPath("Path_CE", 2, 4, 300);

    }

    private void addFlightPath(String pathId, int sourceAirport, int destAirport, int distance)
    {
        Edge path = new Edge(pathId, nodes.get(sourceAirport), nodes.get(destAirport), distance);
        flightPaths.add(path); //IndexOutOfBounds exception is thrown here
    }

}

Stack Trace

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at core.dijkstras2.DijkstrasController.addFlightPath(DijkstrasController.java:83)
    at core.dijkstras2.DijkstrasController.populateDijkstrasGraph(DijkstrasController.java:63)
    at core.dijkstras2.DijkstrasController.<init>(DijkstrasController.java:19)
    at core.dijkstras2.DDriver.main(DDriver.java:10)
LuCio
  • 5,055
  • 2
  • 18
  • 34
  • `at java.util.ArrayList.get(ArrayList.java:433)` this makes me believe you are getting the error at the line above the one you are describing, in one of the calls to `nodes.get()`. `ArrayList add(E e)` does not throw the exception you are getting. https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html#add-E- – Robert Jul 24 '18 at 12:06
  • `flightPaths.add(path); //IndexOutOfBounds exception is thrown here` - I suppose it's not that line but the previous as the stacktrace shows: `at java.util.ArrayList.get(...)`. Thus either `sourceAirport` or `destAirport` is not a valid index of `nodes`. At this time `nodes` has only one element at index `0` as its size is `1`. – LuCio Jul 24 '18 at 12:06
  • The Exception is thrown in the ``get`` method, look at the stacktrace. – f1sh Jul 24 '18 at 12:07
  • @LuCio Figured the problem out. I'll update with an answer. –  Jul 24 '18 at 12:15
  • Yeah, you probably need to populate the `nodes` List first before adding to the `flightPaths`. – afrischke Jul 24 '18 at 12:15
  • So basically you're trying to build edges betwenn nodes that aren't present yet. Therefore you should build up the `nodes` from the database first and then create the edges between the nodes. – LuCio Jul 24 '18 at 12:16
  • @LuCio Exactly, by including the `addFlightPath()` code within the same for loop the `Nodes` list was not being populated properly. –  Jul 24 '18 at 12:18
  • If someone could confirm my answer I'd appreciate it, as I cannot. –  Jul 24 '18 at 12:18

4 Answers4

1

So, the reason for this IndexOutOfBounds was being caused by the fact that the for loop in question prevented the nodes ArrayList from being populated properly.

To fix this, I simply changed this code:

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);

         //This block of code throws an IndexOutOfBounds error
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }

And moved the second block into a separate for loop, this allows the first for loop to populate the arraylist first, before the flight paths are added.

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);
        }

        for (int i = 0; i < fdb.getDatabaseSize(); i++)
        {
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }
  • I wouldn't say "_IndexOutOfBounds ... prevented the `nodes` from being populated_". It was rather the fact that you tried to build up the nodes and the egdes at the same time. This would only work, if you would create edges between already present nodes which does not match the use case. – LuCio Jul 24 '18 at 12:28
1

As mentioned in the comments, your exception seems to be stemming from the following line:

Edge path = new Edge(pathId, nodes.get(sourceAirport), nodes.get(destAirport), distance);

Let's go over your populateDijkstrasGraph() function (offending portion):

    for (int i = 0; i < (fdb.getDatabaseSize()); i++)
    {
        Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
        nodes.add(location);

Here you add the location given by nodeNumberToNodeLetter(i).

        int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
        int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());

Here, you are getting the integer values for the first two airport nodes. However, we've only added a single node! (nodes.add(location) above).

Thus, if sourceAirport == 0 and destinationAirport == 1, with nodes currently containing only a single Vertex, nodes.get(sourceAirport) will work, whereas nodes.get(destinationAirport) will throw an IndexOutOfBoundsException, as expected.

One way to fix this would be to populate the list of nodes before attempting to populate the edges between them.

Edit: If you haven't already, you should enable line numbers in your IDE. It makes debugging much easier. In addition, you should familiarize yourself with debugging and breakpoints - this would've allowed you to find the above error quite quickly.

filpa
  • 3,651
  • 8
  • 52
  • 91
0

A bit of guess work, but I assume that your working version of the code looks something like this:

public void populateDijkstrasGraph(FlightDatabase fdb)
{
    nodes = new ArrayList<Vertex>();
    flightPaths = new ArrayList<Edge>();
    for (int i = 0; i < (fdb.getDatabaseSize()); i++)
    {
        Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
        nodes.add(location);

     //This block of code throws an IndexOutOfBounds error
     //   AirJourney journey = fdb.getFlightDetails(i);
     //   String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
     //   int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
     //   int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
     //   int distance = journey.getNumberOfMilesToTravel();
     //   addFlightPath(pathId, sourceAirport, destinationAirport, distance);
    }

// Uncommenting this section of code allows the program to function normally
   addFlightPath("Path_AB", 0, 1, 800);
   addFlightPath("Path_BC", 1, 2, 900);
   addFlightPath("Path_CD", 2, 3, 400);
// etc.

This will work fine since you have a fully populated nodes List. If you move addFlightPath into the for-loop though, nodes will only contain one element in the first iteration through the loop. Hence the call to nodes.get(1) will fail with the IndexOutOfBounds exception.

You will probably need to loop twice:

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
{
    Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
    nodes.add(location);
}

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
{
    AirJourney journey = fdb.getFlightDetails(i);
    String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
    int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
    int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
    int distance = journey.getNumberOfMilesToTravel();
    addFlightPath(pathId, sourceAirport, destinationAirport, distance);
}
afrischke
  • 3,836
  • 17
  • 30
-6

When you do a loop always start from 0 to size -1 of the list you use. If you have a list of 5 position, the loop goes from 0 to 4. Maybe its your problem?

Try to put:

for (int i = 0; i < (fdb.getDatabaseSize()-1); i++)
{}
SHR
  • 7,940
  • 9
  • 38
  • 57