Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (731)
Games in Android Showcase (217)
games submitted by our members
Games in WIP (798)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  How do I iterate through a list that is modified outside of the current loop?  (Read 679 times)
0 Members and 1 Guest are viewing this topic.
Offline kingAree

Senior Newbie


Exp: 4-6 months



« Posted 2017-06-07 14:02:06 »

So I'm implementing Separating Axis Theorem right now and currently it works perfectly when just looping through two objects, however if I were to add any more objects to my List then the code would break without errors:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
public boolean separatingAxisTheorem(){
      //this method is being called constantly in my update methods

    for(DevEntity e : handler.getDevWorld().getDevM().getDevEntities()){
     //here I am looping through a list of the entities in my world


        obtainEdges();

        if(!e.equals(this)){

            Vector2[] axes1 = axis;
            Vector2[] axes2 = e.axis;

            for(int i = 0; i < axes1.length; i++){
                Vector2 axis = axes1[i];

                p1 = new Vector2(projectAxis(axis));
                p2 = new Vector2(e.projectAxis(axis));

                if(!p1.overlap(p2)){
                    return false;
                }
            }

            for(int i = 0; i < axes2.length; i++){
                Vector2 axis = axes2[i];

                p3 = new Vector2(projectAxis(axis));
                p4 = new Vector2(e.projectAxis(axis));
                if(!p3.overlap(p4)){
                    return false;
                }
            }
        }  
    }
    return true;
}


This is how I add to the list in my World class:

1  
2  
3  
4  
    devM = new DevEntityManager(handler, new DevPlayer(handler, (1270/2) - 
    32, (720/2) - 32));
    devM.addDevEntity(new DevSquareEnemy(handler, 200, 400));
    //devM.addDevEntity(new DevTriEnemy(handler, 200, 100));



With the second addition commented out my code works fine and my code returns true/false depending on if my player is intersecting my DevSquareEnemy object, however if I remove the comment then my code will only return false, and I think this is because of the way I am adding my objects to the list, I have tried replacing my for loop with an Iterator and while loop but then I started receiving ConcurrentModificationException's
Offline princec

« JGO Spiffy Duke »


Medals: 906
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #1 - Posted 2017-06-07 14:36:34 »

If you actually need to iterate a list that is modified outside of its current loop, you need a CopyOnWriteArrayList, or if it's certainly going to be modified every time, just iterate through a copy of the list instead.

If you actually need to iterate through the newly added elements, you can't use an iterator. It's also probably not the design you're looking for though there are sometimes good reasons to do that.

Cas Smiley

Offline crockid5

Senior Newbie


Medals: 1



« Reply #2 - Posted 2017-06-07 15:28:33 »

Use a standard for loop like so:


1  
2  
3  
4  
5  
    List<DevEntity> devEntities = handler.getDevWorld().getDevM().getDevEntities();

    for(int i = 0; i < devEntities.size(); i++ ){
        DevEntity e = devEntities.get(i);
        //....
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline kingAree

Senior Newbie


Exp: 4-6 months



« Reply #3 - Posted 2017-06-07 20:27:06 »

Like this?

1  
2  
3  
CopyOnWriteArrayList<DevEntity> des = new CopyOnWriteArrayList<DevEntity>(handler.getDevWorld().getDevM().getDevEntities());
     
      for(DevEntity e : des){
Offline sarcastibots

Junior Devvie


Medals: 2
Projects: 1



« Reply #4 - Posted 2017-06-07 20:56:05 »

I believe the field in DevWorld that contains the entities would be a CopyOnWriteArrayList, and then you would use a standard list reference in the SAT method. The for-each structure may not work depending on how it's implemented, and you'd need to reinitialize the iterator every time the SAT method is called to make sure you are iterating over a current copy of the list.

You could also consider setting up a second data structure to hold new objects while the current objects are being acted upon. Then merge the two structures when neither is being iterated/modified.

something like this.
1  
2  
3  
4  
5  
6  
7  
8  
List<DevEntity> currentEntities
List<DevEntity> entitiesToAdd

update (){
    SAT(currentEntities)

    merge(currentEntities, entitiesToAdd)
}

Offline philfrei
« Reply #5 - Posted 2017-06-07 22:19:45 »

CopyOnWriteArray is used very much like an ArrayList. So yes, the declaration you wrote looks good.

CopyOnWriteArray is concurrency safe, so you can add to it or delete from it from another thread, even during an iteration. What happens is basically this: the new item (or lack of item) becomes part of the next iteration when a new "snapshot" of the list is taken.

CopyOnWriteArray works best in situations where iterations greatly outnumber adds and deletes to the list, assuming nothing will break when the "snapshot" list runs to completion.  If that doesn't describe your situation, maybe we can help come up with some alternate plans.

music and music apps: http://adonax.com
Offline kingAree

Senior Newbie


Exp: 4-6 months



« Reply #6 - Posted 2017-06-08 13:24:48 »

Hi, so that declaration didn't work, nothing changed and my SAT code did not recognise my DevWorld objects, and correct I will be rarely adding/removing to the ArrayList.
Offline sarcastibots

Junior Devvie


Medals: 2
Projects: 1



« Reply #7 - Posted 2017-06-08 18:30:54 »

Quote from: kingAree
... that declaration didn't work ...

Which declaration of CopyOnWriteArray did't work; the one you proposed, the one I proposed, both?

Offline kingAree

Senior Newbie


Exp: 4-6 months



« Reply #8 - Posted 2017-06-09 09:21:36 »

The one I wrote
Offline princec

« JGO Spiffy Duke »


Medals: 906
Projects: 3
Exp: 16 years


Eh? Who? What? ... Me?


« Reply #9 - Posted 2017-06-09 09:47:08 »

It's perfectly fine.

You can even cut out some cruft:

CopyOnWriteArrayList<DevEntity> des = new CopyOnWriteArrayList<>(handler.getDevWorld().getDevM().getDevEntities());

No need to redeclare the generic type.

In any case you've got completely the wrong end of the stick. If you're just going to take a copy of your DevEntities list anyway, you have already done all the work the CopyOnWriteArrayList was going to do for you anyway. The idea is that the list returned by getDevEntities is already a CopyOnWriteArrayList, which means you can iterate through it and modify it to your heart's content.

Cas Smiley

Pages: [1]
  ignore  |  Print  
 
 

 
Archive (335 views)
2017-04-27 17:45:51

buddyBro (533 views)
2017-04-05 03:38:00

CopyableCougar4 (975 views)
2017-03-24 15:39:42

theagentd (1011 views)
2017-03-24 15:32:08

Rule (991 views)
2017-03-19 12:43:22

Rule (972 views)
2017-03-19 12:42:17

Rule (968 views)
2017-03-19 12:36:21

theagentd (1068 views)
2017-03-16 05:07:07

theagentd (982 views)
2017-03-15 22:37:06

theagentd (758 views)
2017-03-15 22:32:18
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!