-1

I have a quick question that involves one ArrayList, 2 Iterators, and some nested for loops. Im trying to make a bit of a gravity engine using multiple gravity wells pulling on each other and moving around. To do this, Iv made an ArrayList of these gravity wells, all randomly places on the screen with a random size. Here it is for reference.

for(int i = 0; i < amount; i++){ // makes all 
      int mass = rand.nextInt(45,65);
      int locX = rand.nextInt(50, getWidth()-100);
      int locY = rand.nextInt(50, getHeight()-100);
      Color cColor = rand.nextColor();

      if(mass%8==0){
        mass = rand.nextInt(25,35);
      }
      else if(mass%7==0){
        mass = rand.nextInt(75,85);
      }


      Body body = new Body((double)locX,(double)locY,mass);
      body.setFilled(true);
      body.setColor(Color.WHITE);
      body.setFillColor(cColor);
      add(body);
      bodys.add(body);
    }

bodys is the name of the ArrayList containing everything. So my real problem comes to the Iterators. Heres the code thats giving me trouble:

  public void move(){
    Iterator<Body> eIter = bodys.iterator();
    while(eIter.hasNext()){ // finding the thing we edit
      Body edit = eIter.next();

      int addX = 0, addY = 0;
      int totalX = 0, totalY = 0;
      double ex = edit.getX(), ey = edit.getY();
      double eMass = edit.getMass(), eSize = edit.getHeight();
      double eMoveX = edit.getMoveX(), eMoveY = edit.getMoveY();
      int placeInArrayEdit = bodys.indexOf(edit);

      Iterator<Body> fIter = bodys.iterator();

      while(fIter.hasNext()){ // iterating through the force pulling the edit body
        Body force = fIter.next(); /// ConcurrentModificationException is thrown
        int placeInArrayForce = bodys.indexOf(force);

        if(placeInArrayForce != placeInArrayEdit){ // making sure the 2 bodys arent the same

          double fx = force.getX(), fy = force.getY();
          double fMass = force.getMass();
          double fMoveX = force.getMoveX(), fMoveY = force.getMoveY();


          double difX = (ex-fx);
          double difY = (ey-fy);

          double distX = distanceP(ex, fx);
          double distY = distanceP(ey, fy);

          double vecX = (difX/distX);
          double vecY = (difY/distY);

          if(distance(fx,ex,fy,ey) <= eSize/3){ // if they are colliding
            if(eMass >= fMass){
              remove(edit);
              edit.addMass((int)(fMass));
              eIter.remove(); // problem
            }
            if(eMass < fMass){
              remove(force);
              force.addMass((int)(eMass));
              fIter.remove();
            }
          }

          double grav = (eMass/fMass);
          grav -= (grav*.50);

          addX -= (vecX/grav)/2; // this determines movement which means i
          addY -= (vecY/grav)/2; // need to edit this with fMass
        }
        edit.setVelX(addX/(eMass + (eMass*.75)));
        edit.setVelY(addY/(eMass + (eMass*.75)));

        edit.addMoveX(edit.getVelX());
        edit.addMoveY(edit.getVelY());

        edit.move(edit.getMoveX(),edit.getMoveY());
      }
    }
  }

The code above is moving the gravity wells and testing for collision. The problem is that ConcurrentModificationException is thrown where iv commented it to be thrown.

Iv spent about an hour or so looking around for a solution and nothing iv tried has worked. The code works up until the wells actually hit each other, then the error is thrown. Is there a way to avoid this error while still testing for collision like this, or is my code just too broken?

Thanks for all the help! Please let me know if you need anything clarified as this is my first question on StackOverflow

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • can you send me an eclipse project for this? – CA Martin May 30 '16 at 18:53
  • as I said previously, Im new to stackoverflow, so I dont know how to contact you. It would be much appreciated if you could tell me. –  May 30 '16 at 19:00
  • We have to keep all answers and questions here in this site.. but if you go to my user profile you will find me on ispecsoft.com – CA Martin May 30 '16 at 19:07
  • 1
    The point of this site is to build a question and answer corpus that future readers can find help with. Exchanging help via other sites/privately somewhat defeats the purpose. I'm not going to stop you - obviously, I can't - but consider deleting this question once you have made contact "externally", because this question won't be of use to others. – Andy Turner May 30 '16 at 19:13
  • @Spagett Please post the code for the `remove(edit)` method. – Andy Turner May 30 '16 at 19:14
  • As I said in my comment.. we have to answer questions and post answers here.. out of respect for you all that are providing this.. I respect you enough to honor you in this way... Maybe you should consider adding a way for users to chat and share info regardless of how many points a "New" user has? Then we could actually "Help" new users more efficiently..? – CA Martin May 30 '16 at 19:15
  • @AndyTurner Problem is unrelated to `remove(edit)`. It's caused by the `eIter.remove()` call two lines down. – Andreas May 30 '16 at 19:23
  • @Andreas yes, I see that now, and have upvoted your answer correspondingly :) – Andy Turner May 30 '16 at 19:24
  • @Andreas although... I'm still a bit suspicious of seeing `remove(edit)` and `eIter.remove()` (where that would remove `edit` from the collection) in the same breath. – Andy Turner May 30 '16 at 19:25
  • @CAMartin You don't need an eclipse project to help with this. If you need clarification about code not displayed, ask for it in a comment, e.g. like AndyTurner asked for the code of `remove(edit)`. – Andreas May 30 '16 at 19:27
  • There are several variables and libraries the OP used in their code... which were not provided.. It's a whole lot easier to see what they are doing in their project than to keep typing back and forth LIKE THIS HAS GOTTEN INTO.... LET'S JUST FORGET IT.... – CA Martin May 30 '16 at 19:30
  • 1
    @CAMartin there's no need for the attitude. If OP's question really needs an entire eclipse project in order to provide an answer, it is too broad a question for the format of SO. Questions like this should present a [minimal, complete, verifiable example](http://stackoverflow.com/help/mcve). Posting an eclipse project might be *complete*, but it is certainly not *minimal*, especially as this behaviour isn't actually related to eclipse. – Andy Turner May 30 '16 at 19:39
  • What attitude are you referring to? YOU ARE REFERRING TO CAPITAL LETTERS?? Attitude would be saying something offensive. By the way are you and @Andreas principles or owners of stackoverflow? – CA Martin May 30 '16 at 19:42
  • Calm down ya'll. :p The line where the exception is thrown is pointed out in the code, and Iterator + remove is a pretty well known cause of CME.. What's been made available here is perfectly acceptable both for offering suggested fixes and for diagnosing the problem. – Monkeygrinder May 30 '16 at 19:47

1 Answers1

4

See javadoc of ArrayList:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

So, you have 2 iterators: eIter for the outer loop, and fIter for the inner loop.
When you call eIter.remove(), fIter will go bad.
When you call fIter.remove(), eIter will go bad.
(If you had called bodys.remove(index), both would go bad.)

Either way, one of the iterators will be stale, and will throw ConcurrentModificationException when you call next().

Also, when you call eIter.remove(), you don't break out of the inner loop, so you run the risk of trying to do it again in another iteration of the inner loop.

In short, you need to find another way, e.g. using indexes and get(index) calls, or something like that.

Andreas
  • 154,647
  • 11
  • 152
  • 247