• Post Reply Bookmark Topic Watch Topic
  • New Topic

Using two iterators on same collection

 
Yogesh Mashalkar
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi,
Just tried using two iterators on the same collection(Vector in this case),but getting the ConcurrentModification Exception sometimes.
The error occurs randomly with no predicted behaviour.
Not able to pin point the source of error
Here is the snippet, line of error is indicated in comment

Would be grateful for any explanation..Thnx


[ Added code tags - Jim ]
[ May 30, 2007: Message edited by: Jim Yingst ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I added code tags to your post. Please use them in the future - they make the code more readable.

Basically, you can't use two Iterators on the same Vector simultaneously. Not for Vector, ArrayList, LinkedList, or other common collections. But it's not necessarily true for all collections - check documentation to see if they mention ConcurrentModificationException. This is intended as a safety feature to check against careless use of threading. Unfortunately in this case, it just gets in the way, as you're not even using threading. Probably the simplest workaround is, instead of Iterators, just use two int indices i and j, and loop through the Vector using the indices:

Yes, usually it's recommended to use Iterators instead of indices like this. But you've found an unusual case where that doesn't quite work. Be careful not to mix up the i and j; that's easy to do accidentally.
 
Yogesh Mashalkar
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
yeah the normal looping is simpler definitely,but funny thing is ive tweaked this code arnd and found that it works well for most situations except for a few ones....

dunno why is there an uncertainity in the behaviour of the code

can the Vector method setElementAt be used while iterating on it!??
i saw somewhere on the net that one cant use even the iterator.remove() method while using two iterators on the same collection.is this statement true?

problem is i cannot modify the coding style as this has been coded by someone else n i have to fix this "special" bug...

sorry for missing the code tag..will take care in future!

thnx
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[Yogesh]: dunno why is there an uncertainity in the behaviour of the code

Well, the error you're getting occurs when you are using at least one Iterator, and the underlying collection is modified in any way other than by using that one Iterator. So if you are using one Iterator and do a remove() using a different Iterator (on the same collection), or if you use a removeElementAt() or add() or other method on the collection itself, then the iterator will probably throw an exception. If you don't see that happen most of the time in this code, I'm guessing you don't normally have to remove elements from the collection while you're iterating. If you can guarantee that never happens, then good. Otherwise you will probably need a somewhat different algorithm.

[Yogesh]: can the Vector method setElementAt be used while iterating on it!??

Actually yes, I think so. For some reason, this method doesn't seem to be included in the comodification check. You can look at the source code in src.jar, for Vector.java and AbstractList.java. Pay attention to the code that changes modCount and expectedModCount (in AbstractList.Itr). Any time the expectedModCount does not match the actual modCount, it's assumed that you're using other threads incorrectly, and a ConcurrentModificationException is thrown. For whatever reason, setElementAt() does not alter the modCount, so it should work. I don't know why they did it that way. Most other methods which alter the Vector would change the modCount.

[Yogesh]: i saw somewhere on the net that one cant use even the iterator.remove() method while using two iterators on the same collection.is this statement true?

Yes. Iterator.remove() works while you're iterating with the same iterator, but if you also use a second iterator, the iterators will become upset.

[Yogesh]: problem is i cannot modify the coding style as this has been coded by someone else n i have to fix this "special" bug...

That's unfortunate, because I don't think you will be able to fix the bug without changing the style. However I'm not sure what the code is supposed to be doing. I see it's more complex than I assumed initially, and simply replacing the Iterators with an old-fashioned for loop may not be enough.

I note that you apparently need the index values anyway.

That indexOfCompareEvent is the exact same value I called "i"in my code above. If you need that value anyway, the way I showed seems simpler. Also, it looks like you only care about compareEvents that have a higher index than the currentEvent. So it's simpler to just start the inner loop index at the currentEventIndex + 1:

Blech. I prefer the shorter variable names, like i and j.

Later when you call

you can replace those with

The decrement is to account for the fact that since you just removed one, the next time through the loop you want to visit the same position, which now contains the element that was just after the one you removed.

Also, as near as I can tell,

does nothing, since the currentEvent object is still located in visualEvents, at the same index it was when you originally found it. You are replacing that object with itself.

Beware that I may well have misunderstood some parts of the code, as I just looked at it, haven't tested it, and I'm not sure I understood the goal. So anything I say, you may need to modify it or ignore it. You have been warned.
 
Yogesh Mashalkar
Greenhorn
Posts: 25
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
thnx a ton Jim!!
really appreciate the concern shown in this regard....

whatever may be the outcome of this bug..but am surely thrilled to understand these new concepts...

and yes the warning has been understood...
thnx again!
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!