Итерация по списку в Java - PullRequest
1 голос
/ 27 мая 2011

Проблема заключается в следующем:

Напишите подмножества статических методов, которые используют рекурсивный возврат, чтобы найти все возможные подсписки данного списка. Подсписок списка L содержит 0 или более элементов L. Ваш метод должен принять список строк в качестве параметра и распечатать каждый подсписок, который может быть создан из элементов этого списка, по одному на строку. Например, предположим, что переменная с именем list хранит следующие элементы:

[Janet, Robert, Morgan, Char]

вызов подмножеств (список); будет производить вывод, такой как следующий:

[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]
[]

Часть моего решения требует использования рекурсивного возврата:

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);
      }

Но я получаю исключение ConcurrentModificationException в строке, содержащей itr.add (слово). Зачем? Я думал, что весь смысл ListIterator состоит в том, чтобы избежать этой проблемы?

РЕДАКТИРОВАТЬ: Я также пытался решить это так:

for (String word : choices) {
         List<String> choicesCopy = choices;
         chosen.add(word);
         choicesCopy.remove(word);
         subsets(choicesCopy, chosen, alreadyPrinted);
      } 

Я все еще получаю исключение одновременной модификации .... :( Как это происходит? Там нет никаких изменений в первоначальном списке ...

Ответы [ 4 ]

2 голосов
/ 27 мая 2011

Не совсем, проблема в том (скорее всего), что вы создаете ListIterator() каждый раз, когда вы идете рекурсивно.Каждый итератор списка пытается изменить один и тот же базовый список слов, что вызывает исключение.Это недопустимо.

Решение состоит в том, чтобы предоставлять копию списка слов каждый раз, когда вы выполняете рекурсивный анализ.Таким образом, каждый итератор списка будет работать со своим личным списком.

0 голосов
/ 27 мая 2011

В вашем втором решении есть простая ошибка.

List<String> choicesCopy = choices;

Это не создает копию списка.Вы можете использовать ArrayList.clone () или LinkedList.clone () или создать новый список, подобный этому

List<String> choicesCopy = new LinkedList<String>(choices);
0 голосов
/ 27 мая 2011

вы создаете новый итератор при каждом вызове рекурсии, а затем удаляете / добавляете его. Когда вы поднимаетесь в стек, старый итератор обнаруживает изменения и выдает исключение.

Вам следует переосмыслить этот код.

0 голосов
/ 27 мая 2011

РЕДАКТИРОВАТЬ: я пропустил, что OP использовал ListIterator.

Причина ConcurrentModificationException в том, что вы изменяете базовый список, добавляя и удаляя элементы изэто пока вы перебираете это.Я полагаю, что вам придется использовать более примитивную технику итерации, такую ​​как традиционный цикл for, и самостоятельно отслеживать значение итерации.

По приведенной выше ссылке:

, еслипоток изменяет коллекцию напрямую, в то время как он выполняет итерацию по коллекции с помощью итератора, работающего при сбое, итератор сгенерирует это исключение

Здесь - еще одна быстрая статья об этом.

...