vigna / fastutil

fastutil extends the Java™ Collections Framework by providing type-specific maps, sets, lists and queues.
Apache License 2.0
1.76k stars 196 forks source link

ObjectArrayList removing into foreach #243

Closed PedroMPagani closed 3 years ago

PedroMPagani commented 3 years ago

Alright, i have this code and when u run it, it removes the /2 of the list size, not it all, when i remove using the iterator and nextIndex() works fine, but when i try it inside of the foreach it does not work, and it runs only the half of the list on the foreach either, not it all. ` ObjectList s = new ObjectArrayList();

 for (int i = 0; i < 10000; i++) {
        STotem st = new STotem(String.valueOf(i), String.valueOf(i));
        st.setRankWeight(i*10000);
        s.add(i,st);
        System.out.println("Add: " + " : " + i);
    }
    System.out.println(s.size());
    Long time1 = System.currentTimeMillis();
    for (Object o : s) {
        s.remove(o);
    }
    /*ObjectListIterator g = s.listIterator();
    while (g.hasNext()){
        s.remove(g.nextIndex());
    }*/
    Long time2 = System.currentTimeMillis();
    System.out.println("Size of the list: " + s.size() + " " + (time2-time1));`
incaseoftrouble commented 3 years ago

Concurrent modification (i.e. modification while iterating) is not allowed, fastutil does not exhaustively try to detect such modification for performance reasons. Both loops are invalid in that sense. Any modification to a collection effectively invalidates any existing iterators (except if the modification is performed through the iterator).

Instead of s.remove(g.nextIndex()) you could use something like g.remove() (I think this is how it is called).

To remove all objects, use s.clear(). If you want to select which to remove, use s.removeIf(...) or make a copy of the list.

incaseoftrouble commented 3 years ago

For further help, search for ConcurrentModificationException and how to avoid it (this is what most java collections would directly throw for this kind of code).

PedroMPagani commented 3 years ago

While using g.remove() it gives me an error, Exception in thread "main" java.lang.IllegalStateException at it.unimi.dsi.fastutil.objects.ObjectArrayList$1.remove(ObjectArrayList.java:895) at com.styp.totem.manager.STRank.(STRank.java:60) at com.styp.totem.manager.STRank.main(STRank.java:37) twasfagfwa

incaseoftrouble commented 3 years ago

You also need to call g.next() after removing (or potentially before it, I am not entirely sure!). .remove() does not advance the iterator.

So something like

while (g.hasNext()) {
  g.next();
  g.remove();
}
PedroMPagani commented 3 years ago

Sorry for the dumb act, thanks for the support. ( I think its before.)

incaseoftrouble commented 3 years ago

Sorry for the dumb act, thanks for the support. ( I think its before.)

No problem 😄 Happens to everyone.