説明のために - 私はArrayListから何も削除したくありません。したがって、私が見つけたすべての回答の90%は実際には適用されません。私はここで何かを見つけることができない、または他の場所で私を助けてくれます!ArrayListでConcurrentModificationExceptionを回避するにはどうすればよいですか?
私は、対戦相手(コンピュータ)が本質的に不正行為を行っているハングマンをプレイするJavaアプリケーションを作成しています。単語を「選択」しないという意味で、単語群を持ち、プレイヤーの推測が正しい、または間違っているかどうかを判断することができます。一言で言えば
、私の問題はこれです:
必要になります場合、私は、私は言葉のセットを持ってArrayListを、masterList
、辞書を持っており、様々な方法がさまざまなタスクを実行するには、このを反復。私のコードはシングルスレッドであり、2番目の反復でArrayList内の次のオブジェクトにアクセスしようとすると、これらのメソッドの1つがConcurrentModificationException
を投げています。しかし、反復処理中にArrayListを実際に変更するものは見つかりません。
import java.io.*;
import java.util.*;
public class Main {
private ArrayList<String> masterList;
private ArrayList<String> contains;
private ArrayList<String> doesNotContain;
private HashMap<Integer, ArrayList<String>> wordLengthList;
private HashMap<Integer, ArrayList<String>> difficultyList;
private int guesses = 10;
private Scanner sc;
private FileReader fr;
private BufferedReader br;
private String guessString;
private char guessChar;
private static final String DICTIONARY = "smalldictionary.txt";
private String wordLengthString;
private int wordLengthInt = 0;
public Main(){
masterList = new ArrayList<String>();
contains = new ArrayList<String>();
doesNotContain= new ArrayList<String>();
wordLengthList = new HashMap<Integer, ArrayList<String>>();
difficultyList = new HashMap<Integer, ArrayList<String>>();
sc = new Scanner(System.in);
importTestDictionary(); //does not use masterList
br = new BufferedReader(fr);
importWords(); //Adds to masterList. Both readers closed when finished.
catalogLengths(); //Iterates through masterList - does not change it.
do{
setWordLength(); //does not use masterList
}while(!(validateLengthInput(wordLengthString))); //validation will change the set of masterList if valid.
//Main loop of game:
while(guesses > 0){
do{
getUserInput();
}while(!(validateInput(guessString)));
splitFamilies();//will change set of masterList when larger group is found. Changes occur AFTER where Exception is thrown
printDifficultyList();
}
}
private void importWords(){ //Adds to masterList. Both readers closed when finished.
try{
while(br.readLine() != null){
line = br.readLine();
masterList.add(line);
}
br.close();
fr.close();
}catch(IOException e){
System.err.println("An unexpected IO exception occurred. Check permissions of file!");
}
}
private boolean validateLengthInput(String length){ //validation will change the set of masterList if valid.
try{
wordLengthInt = Integer.parseInt(length);
if(!(wordLengthList.containsKey(wordLengthInt))){
System.out.println("There are no words in the dictionary with this length.\n");
return false;
}
}catch(NumberFormatException e){
System.out.println("You must enter a number.\n");
return false;
}
masterList = wordLengthList.get(wordLengthInt);
return true;
}
private void splitFamilies(){ //will change set of masterList when larger group is found. Changes occur AFTER where Exception is thrown
Iterator<String> it = masterList.iterator();
int tempCount = 0;
while(it.hasNext()){
tempCount++;
System.out.println("tempCount: " + tempCount);
String i = it.next(); //Still throwing ConcurrentModification Exception
if(i.contains(guessString)){
contains.add(i);
}else{
doesNotContain.add(i);
}
}
if(contains.size() > doesNotContain.size()){
masterList = contains;
correctGuess(); //does not use masterList
profileWords();
}
else if(doesNotContain.size() > contains.size()){
masterList = doesNotContain;
incorrectGuess(); //does not use masterList
}
else{
masterList = doesNotContain;
incorrectGuess(); //does not use masterList
}
}
private void printMasterList(){ //iterates through masterList - does not change it.
for(String i : masterList){
System.out.println(i);
}
}
private void catalogLengths(){ //Iterates through masterList - does not change it.
for(String i : masterList){
if(i.length() != 0){
if(!(wordLengthList.containsKey(i.length()))){
wordLengthList.put(i.length(), new ArrayList<String>());
}
wordLengthList.get(i.length()).add(i);
}
}
}
}
例外が送出された行は、コードの上にマークされています。 masterList
を使用する方法もマークされていますが、使用されていない方法は含まれていません。コメントはありません。
私はいくつかの回答を読んで、そのうちのいくつかは例外を避けるためにIterator
を使用するよう提案しました。これは上記のsplitFamilies()
で実装されています。元のコードは以下の通りだった:例外がスローされたとき
private void splitFamilies(){ //will change set of masterList when larger group is found. Changes occur AFTER where Exception is thrown
int tempCount = 0;
for(String i : masterList){ //This line throws ConcurrentModificationException
tempCount++;
System.out.println("tempCount: " + tempCount);
if(i.contains(guessString)){
contains.add(i);
}else{
doesNotContain.add(i);
}
}
....continue as before
tempCount
は常に2
です。
私は本当にシンプルなものを見逃しているかもしれませんが、私はこれをトレースしようとしましたが、なぜこの例外が出ているのか分かりません!
私はコードとは無関係にすべてを削除しようとしましたが、本当に誰かが完全なものを見たいと思えば、私はすべてのコードを質問にダンプすることができますね!
'masterList'を反復しながら' contains'と 'doesNotContain'に追加します。これは同じものを参照している可能性があります。 – shmosel
'masterList = contains'や' masterList = doesNotContain'を行います。次に、 'contains'または' doesNotContain'に追加しようとします。 shmoselが言ったように、 'masterList'はあなたが変更しようとしているのと同じリストを参照します。あなたは反復処理中にリストを修正しようとしているので、 'ConcurrentModificationException'がスローされているので、それらの答えの90%が**適用されます**リストを反復しながら**変更**しようとしました。 –
NB 'while(br.readLine()!= null)'および次の 'readLine()'呼び出しが正しくありません。偶数行のみが表示されます。 'while((line = br.readLine())!= null)'に 'readLine()'を入れないでください。 – EJP