0

For this program, I read in a excel file that lays out a map of towns, towns adjacent to them, and the distance between them, which looks like:

Bourke  Nyngan  200
Brewarrina  Walgett 134
Broken Hill Mildura 266
Broken Hill Wilcannia   195
Bungendore  Queanbeyan  54
etc.

And that's working great. Everything seems perfect. I'm trying to make a program that if I give it two towns, it returns the shortest possible path between the two.

I can get my program to correctly read in the file, and set up everything, so I know that this issue isn't anything to do with the setup. To the best of my knowledge this part of my program works, as my program can get through it without throwing errors:

   //returns the Vertex with the smallest distance from a list of Vertices
   public static Vertex minDist(List<Vertex> Q){
  int min = 2147483647;
  Vertex closest = new Vertex("Closest");

  for(Vertex v : Q){
     if(v.distance < min){
        closest = v;
     }
  }   
  return closest;
  }


 //used to relax (change the distance of a town)
 public static void relax(Vertex u, Vertex v, int w){
  if(v.distance > u.distance + w){
     v.distance = u.distance + w;
     v.predecessor = u;
    } 
   }



public static void Dijkstra(Graph G, Vertex s){
  Vertex u = new Vertex("not good");
  List<Vertex> Q = V;
  Vertex v = new Vertex("oh no");

//while Q is not empty:
  while(!Q.isEmpty()){

  //the vertex in Q that has the smallest distance (at first s with 0, then we relax and that changes things)
     u = minDist(Q);

     if(u.name.equals("Closest")){
        //Q.remove(u);
        return;
     }
     Q.remove(u);

     S.add(u);


  //for each edge e in u's adjacencyList:
     for(Edge e : u.roadList){

        if(e != null && !e.finish.name.equals(u.name) ){
           v = e.finish;

           relax(u,v,w(u,v)); //w(u,v) returns the distance between u and v
        }

     }
  } 

  System.out.println("Q is null");  
}

So I have that, and things look okay to me. I know it's a bit Frankenstein'ed together, but I got it to at least run without errors, because the ConcurrentModificationException gets thrown AFTER this method returns in my main method.

This is where my Dijkstra method gets called in my main method. I never reach the line in my code that prints "SHOULD REACH HERE" because the program throws the ConcurrentModificationException.

        //if both towns exist and are unique, find the shortest route between them.
        if(isTown(town1,V) && isTown(town2,V) && !town1.equals(town2)){

           for(Vertex f : V){
              if(f.name.equals(town2)){
                 destination  = f;
              }
           }

           System.out.println("Traveling...");

           Graph G = new Graph(V,E);

           for(Vertex s : V){

              if(s.name.equals(town1)){
              //////////////////DIJKSTRA STUFF GOES HERE///////////////////
                 initialize(G,s);

                 Dijkstra(G, s);
                 System.out.println("FINISHED DIJKSTRA");

                 //Print out the things in the vertex array S with their distances.
                 for(Vertex b : S){
                    System.out.println(b.name + " (" + b.distance + ")");
                 }

               ///////////////////////////////////////////////
              }

           }
           System.out.println("SHOULD REACH HERE");
        }

I have never seen a ConcurrentModificationException, my lab TA has never seen a ConcurrentModificationException, and even my professor has never seen a ConcurrentModificationException. Can I get some help with avoiding this? A person in a higher class said that he has only seen this happening when working with multiple threads, and I don't even know what that really means so I assume my program doesn't do that.

If I run the program with with town1 = Grafton and town2 = Bathurst, then the output should be:

First town: Grafton
Second town: Bathurst
Bathurst (820)
Lithgow (763)
Windsor (672)
Singleton (511)
Muswellbrook (463)
Tamworth (306)
Bendemeer (264)
Uralla (218)
Armidale (195)
Ebor (106)
Grafton

But is instead

First town: Grafton
Second town: Bathurst
Grafton (0)
Glen Innes (158)
Inverell (225)
Warialda (286)
Coffs Harbour (86)
I/O error: java.util.ConcurrentModificationException
Lazarus
  • 125
  • 2
  • 15

1 Answers1

0

You're getting this because you're removing from Q while iterating over it it. See Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop

Cannoliopsida
  • 3,044
  • 5
  • 36
  • 61
  • I changed the line Q.remove(u); to Q.removeIf(m -> m == minDist(Q)); to like some of the answers there said, and it still throws the exception. Any advice? Also thank you for the answer, that article will hopefully help me out when I show it to my instructor. – Lazarus Dec 07 '17 at 19:02
  • edit: I avoided the exception by making V a CopyOnWriteArrayList() instead of an ArrayList() – Lazarus Dec 08 '17 at 05:47