问题
The problem is as follows:
Write a static method subsets that uses recursive backtracking to find every possible sub-list of a given list. A sub-list of a list L contains 0 or more of L's elements. Your method should accept a List of strings as its parameter and print every sub-list that could be created from elements of that list, one per line. For example, suppose a variable called list stores the following elements:
[Janet, Robert, Morgan, Char]
The call of subsets(list); would produce output such as the following:
[Janet, Robert, Morgan, Char]
[Janet, Robert, Morgan]
[Janet, Robert, Char]
[Janet, Robert]
[Janet, Morgan, Char]
[Janet, Morgan]
[Janet, Char]
[Janet]
[Robert, Morgan, Char]
[Robert, Morgan]
[Robert, Char]
[Robert]
[Morgan, Char]
[Morgan]
[Char]
[]
Part of my solution calls for the use of recursive backtracking:
ListIterator<String> itr = choices.listIterator();
while (itr.hasNext()) {
String word = itr.next();
chosen.add(word);
itr.remove();
subsets(choices, chosen, alreadyPrinted);
chosen.remove(word);
itr.add(word);
}
But I get the ConcurrentModificationException on the line that has itr.add(word). Why? I thought the whole point of the ListIterator is to avoid that problem?
EDIT: I also tried solving it like this:
for (String word : choices) {
List<String> choicesCopy = choices;
chosen.add(word);
choicesCopy.remove(word);
subsets(choicesCopy, chosen, alreadyPrinted);
}
I still get a concurrentmodificationexception.... : ( How is this happening? There is no modification of the original list at all...
回答1:
Not exactly, the problem is (most probably) that you create ListIterator()
each time you go recursive. Each List Iterator is trying to modify the same underlying list of words, which triggers the exception. This is not allowed.
The solution is to provide a copy of the list of words each time you go recursive. Like that, each list iterator will work on its own personal list.
回答2:
you create new iterator on every recursion call and then you remove/add using it. When you go up the stack, old iterator detects change and produces exception.
You should rethink this code.
回答3:
EDIT: I missed that the OP was using a ListIterator
.
The reason for the ConcurrentModificationException is that you are modifying the underlying list by adding and removing elements from it while you are iterating over it. I believe you will have to use a more primitive iteration technique, like the traditional for
loop and keep track of the iteration value yourself.
From the above link:
if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception
Here is another quick article on it.
回答4:
Your second solution has a simple mistake in it.
List<String> choicesCopy = choices;
This does not create a copy of the list. You could use ArrayList.clone() or LinkedList.clone() or create a new list like this
List<String> choicesCopy = new LinkedList<String>(choices);
来源:https://stackoverflow.com/questions/6146690/iteration-over-a-list-in-java