I'm fairly new to programming. I was hoping for some help understanding where I might be going wrong when I inherit from Iterator to make a "safe" iterator, please. This is one that can be used by a client object to iterate through the collection, but not remove anything from it.
When I run my program, I get a ConcurrentModificationException as the Client object's printProducts() method is called and I'm not sure why. Here is the relevant code:
And this is the exception:
Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
Hi Neil. I don't know exactly where it's causing the exception, but I do know you're doing something important wrong, and fixing it might solve your problem.
When you call the iterator() method on an Iterable, it should return a new iterator every time, that will iterate over every element in the Iterable. Instead, you have one iterator, which you return every time. You should first deal with this issue.
Tip: When posting exceptions, make sure the line numbers it refers to match the code you post. So when you have separate source files, post them in separate [code] blocks.
Joined: Dec 09, 2011
Thanks for the helpful and quick reply. Your advice to return a new iterator every time on the iterator() method has fixed the problem. I no longer get an exception.
Welcome to the ranch! (I know am only a few posts old, but hey, couldn't resist )
I can explain to you what a ConcurrentModificationException is, but your program is incomplete, so I can only guess which part of it is giving you the exception. Do post a simple runnable example next time around.
Concept - Once you've created an iterator for a list, it is against the rules of Java to modify the list. When you do so, you get an exception called ConcurrentModificationException. By modification, I mean addition or deletion of the items of the list and not the state of the objects inside the list.
1) Iteration is a pattern wherein you sequence through a collection without paying heed to the underlying structure of the collection. At the current iteration pointer, if hasNext() returns a true, you can either use next() or remove() methods and return valid values, else if false, the methods can return null values.(without throwing an exception).
2) The addition and removal of items of a list are independent operations which have nothing to do with the iterator. The exception only shows that there is coupling between these independent entities which am sure is undesirable.
3) Isnt it a programmer's duty to take care that the iterator is sort of "reloaded" or "refreshed" everytime there is a change in the underlying list.(The jvm libraries could also do this automatically).
Please do tell me if I've missed out a concept in Iterator pattern.
Barney Balboa wrote:1) Iteration is a pattern wherein you sequence through a collection without paying heed to the underlying structure of the collection. At the current iteration pointer, if hasNext() returns a true, you can either use next() or remove() methods and return valid values, else if false, the methods can return null values.(without throwing an exception).
Iterators are supposed to provide us a sequence through the collection, as if it was a snapshot taken at the time when the iterator was created. Hence, any modification to the underlying collection is not handled by guessing what could be the right behaviour. Think about this - there is a list with 10 elements, and you are iterating through it. You have reached to the last element and another thread inserts a value somewhere in between. Now, should the hasNext() return true (because now there is an element which is not yet visited) or false (because originally the list didn't have this new element when the iterator was created). You can argue about these cases, but the condition soon becomes very complex when there are Sets with various sequencing of elements, and insertion or removal of an element during the iteration makes it impossible to guess whether it would be correct to cater for the change or not.
Hence, as a coherent, consistent mechanism, iterators are designed to be fail-fast. This means, that if the collection has been modified during the iteration, and hasNext() or next() is invoked again, they will throw this exception. Please note that it is not the modification of the collection which results in the exception, but the call to hasNext() or next() after the modification.
Barney Balboa wrote:2) The addition and removal of items of a list are independent operations which have nothing to do with the iterator. The exception only shows that there is coupling between these independent entities which am sure is undesirable.
I would argue that iterator does get affected by modifications on the underlying data structure, as it does not create an in-memory snapshot of the data-structure within itself, when created. Instead, it relies on the data-structure to be consistent till it's iteration is finished.
Barney Balboa wrote:3) Isnt it a programmer's duty to take care that the iterator is sort of "reloaded" or "refreshed" everytime there is a change in the underlying list.(The jvm libraries could also do this automatically).
Your explanations make sense. I'll just add one more thing on this and leave it at that. ArrayIndexOutOfBounds is an exception wherein there is an actual mistake committed from the programmer's end, but modifying a collection didnt seem to attribute to a mistake and that is what made me think the use of ConcurrentModificationException.
I verified your statement in bold and that's absolutely correct. I'll post a few more questions on the same, so please bear with me
What actually happens when the subsequent iterator operation is called? I mean how does the iterator get to know that there has been a change in the list.
The data structure simply holds some field containing the amount of modifications that happened to it since it came into existence. When the iterator starts, it records this field, and on each step it checks whether the field still has the same value. If not, a modification occurred during the iteration, and the iterator will throw the exception.
Praveen Kumar M K
Joined: Jul 03, 2011
Yes...A simple check on modification to the size of the collection would do I guess.