Hello everyone. I have a TreeSet<State> that I want to iterator over in order to change the States within the TreeSet (more specifically, a private subclass within each state). However, I will most likely run into problems as I do something like this, or something to this effect:

for(State s : stateMap.values())
		{
			s.addArc();
		}

I will probably get an exception because I'm working on a set being iterated over. How do I avoid this?

Recommended Answers

All 10 Replies

UPDATE: This might give people a better idea of what I have tried to do:

private void addTransitionsToAndFromi(State i)
	{
		LinkedList<State> jStates = new LinkedList<State>();
		for(State s : stateMap.values())
		{
			jStates.add(s);
		}
		
		for(int x=0; x<jStates.size(); x++)
		{
			State j = jStates.get(x);
			for(State k: stateMap.values())
			{
				if(!j.equals(i) && !k.equals(i))
				{
					for(State.arc a : j.getArcs())
					{
						if(a.getState().equals(i))
						{
							for(State.arc b : i.getArcs())
							{
								if(b.getState().equals(k))
								{
									System.out.println(j.toString() + " on a " + a.getTransitionString() + " to " + i.toString() + " on a " + b.getTransitionString() + " to " +  k.toString());
									//Build transition string
									String transitionString = a.getTransitionString();
									
									//Check for loops
									for(State.arc l : i.getArcs())
									{
										if(l.getState().equals(i))
										{
											transitionString += "(" + l.getTransitionString() + ")*";
										}
									}
									
									//Add the 'j' part of the transition string
									transitionString += b.getTransitionString();
									
									System.out.println(transitionString);
									
									j.addArc(transitionString, k);
								}
							}
						}
					}
				}
			}
		}
		stateMap.remove(i.getStateName());
	}

where does stateMap come from?

Member Avatar for ztini

You're thinking you might get a concurrent modification exception? The micro-example you provided looks alright.

You should have no problems adding/deleting/modifying your states mid-iteration.

it might have been a good idea to run your code to confirm your exceptions before posting this (its easier to learn from your own mistakes).

you will only run into problems if you try to remove the State objects from the set returned by stateMap.values() mid iteration; modifying the state objects mid iteration is cool.

So I tested it, and I got a concurrent modification exception on line 16 of the above code:

for(State.arc a : j.getArcs())

So I basically did the same thing as I did on lines 3-7. I made a LinkedList and iterated through it by index, instead of using the built-in iterator class. I think things are up and running now.

My real question is if the above solution is the best route, or if thare are other 'best practices' for doing something like this. It seems to me that in programming there are a lot of

for(Object o : Collection<Object>)

type iterations because they are easy and efficient, but oftentimes we need to modify the contects of said "o".

Any more thoughts?

where does stateMap come from?

The stateMap comes from (global)

TreeMap<State> stateMap

and I'm pulling out the values from the stateMap.

The

//THIS IS TO AVOID CONUCCRENT MOD
LinkedList<State> jStates = new LinkedList<State>();
for(State s : stateMap.values())
{
	jStates.add(s);
}
		
for(int x=0; x<jStates.size(); x++)
{
       State j = jStates.get(x);

//etc....

is my attempt (seems to work, but don't know if it's standard) at fixing this concurrent modification excpetion problem.

In a single-threaded environment you get a ConcurrentModificationException when you modify the Collection that you are iterating over - ie by adding or removing or replacing elements. You don't get an error when you modify the attributes of the individual elements in the Collection (unless they, in turn, cause things to be added to or removed from the collection). In general it's perfectly OK to do this:

for (Thing t : collectionOfThings) {
   t.setX(...
   t.addY(...
}

but not this:

for (Thing t : collectionOfThings) {
   collectionOfThings.add(...
   collectionOfThings.remove(...
}

From what you have posted it looks like you are doing the former, not the latter, so you should not get a ConcurrentModificationException, and there should be no need to use any more complex loops.
Can you post a small runnable version of the code that demonstrates the problem?

The second example (the one that won't work) you gave, JamesCherrill, makes a lot more sense to me now.
If I were to post my code it would take a bit of working and re-writing and such, becuase I have it working just using an iterative for

loop on index i instead of using an iterator, as I explained in my previous posts. So I will spare the extra bloated post.
However, I do believe that the above example by JamesCherrill is a really good one, and right on the money as to what the problem is.

So now that the cat is out of the bag - what would you all suggest as a solution (and best practice) to the above

for (Thing t : collectionOfThings) {
   collectionOfThings.add(...
   collectionOfThings.remove(...
}

code snippet? If I actually do want to iterate through a collectionOfThings and remove or add things?

I actually do want to iterate through a collectionOfThings and remove or add things?

One word: ListIterator
It's "An iterator for lists that allows the programmer to traverse the list in either direction, modify the list during iteration" Documentation is in the usual places

Looks peachy. Thanks again, JamesCherrill!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.