gpt4 book ai didi

java - 无法弄清楚是什么触发了 "java.util.ConcurrentModificationException"

转载 作者:行者123 更新时间:2023-11-30 04:01:11 26 4
gpt4 key购买 nike

我的代码抛出了一个我以前从未见过的错误。所以嘿!我想我正在学习;)无论如何,我做了一些阅读,通常当正在迭代的列表在迭代中被修改时会抛出此错误。不过,我很确定我不会修改它。当在partition()上抛出错误时,如果我没有在updateCurrentList()中为currentList分配新值(通过注释掉代码),程序将不再抛出错误。在我的 play() 方法中,这两个函数被依次调用,但是列表迭代应该在进行更改时完成。我缺少什么?我是否必须以某种方式关闭迭代器?

package hangman;
import java.io.*;
import java.util.*;
import javax.swing.JOptionPane;

public class Hangman {
private Map<String, List<String>> wordPartitions; // groups words according to positions of guessed letter
private List<String> currentList; // remaining possible words that fit the information given so far
Set<Character> wrongGuesses; // holds all the "wrong" guesses so far
StringBuilder guessString; // current state of the word being guessed
String justHyphens; // for checking whether a guess was "wrong"

// initialize fields
// currentList should contain all (and only) words of length wordLength

// justHyphens and guessString should consist of wordLength hyphens
public Hangman(int wordLength) throws FileNotFoundException {
this.currentList = new ArrayList<String>();
addWords(wordLength);
wrongGuesses = new HashSet();

for(int i = 0; i < wordLength; i++) {
justHyphens += "-";
}
guessString = new StringBuilder();
wordPartitions = new HashMap();
}

private void addWords(int wordLength) throws FileNotFoundException {
Scanner words = new Scanner(new File("lexicon.txt"));
String word = "";

while(words.hasNext()) {
word = words.next();
if (word.length() == wordLength) {
currentList.add(word);
}
}
}

// main loop
public void play() {
char choice;

do {
choice = getUserChoice();
partition(choice);
updateCurrentList(choice);
} while (!gameOver());
endMessage();
}

// display the guessString and the missed guesses
// and get the next guess
private char getUserChoice() {
//generate a string from the incorrect choices char list
String wrong = "";
char letter;

if(!wrongGuesses.isEmpty()) {
Iterator<Character> letters = wrongGuesses.iterator();
letter = letters.next();

while(letters.hasNext()) {
letter = letters.next();
wrong += ", " + letter;
}
}

String letterStr = JOptionPane.showInputDialog("Incorrect choices: "+ wrong +"\n Tested letters: "+ guessString.toString() +"\nplease input a letter.");
return letterStr.charAt(0);
}


// use wordPartitions to partition currentList using
// keys returned by getPartitionKey()
private void partition(char choice) {

String word = "";
String key = "";
List<String> tempList = new ArrayList<String>();

Iterator<String> words = currentList.iterator();
//Generate a key for each word and add to appropriate arraylist within map.
while(words.hasNext()) {
word = words.next();
key = getPartitionKey(word, choice);

if(wordPartitions.containsKey(key)) {
tempList = wordPartitions.get(key);
tempList.add(word);
wordPartitions.put(key, tempList);
} else {
tempList.clear();
tempList.add(word);
wordPartitions.put(key, new ArrayList<String>());
}
}
}

// update currentList to be a copy of the longest partition
// if choice was "wrong", add choice to wrongGuesses
// if choice was "right", update guessString
private void updateCurrentList(char choice) {
String key = findLongestList();

currentList = wordPartitions.get(key);

if(key.equals(justHyphens)) {
wrongGuesses.add(choice);
} else {
addLetterToGuessString(guessString, choice, key);
}
}

private String findLongestList() {
Set<String> keySet = wordPartitions.keySet();
Iterator<String> keys = keySet.iterator();
String maxKey = "";
int maxKeyLength = 0;
List<String> tempList;
String tempKey = "";

while(keys.hasNext()) {
tempKey = keys.next();
tempList = wordPartitions.get(tempKey);

if(tempList.size() > maxKeyLength) {
maxKeyLength = tempList.size();
maxKey = tempKey;
}
}

return maxKey;
}

// checks for end of game
private boolean gameOver() {
return false;
}

// display the guessString and the missed guesses
// and print "Congratulations!"
private void endMessage() {
JOptionPane.showMessageDialog(null, "Congrats, yo!");
}

// returns string with '-' in place of each
// letter that is NOT the guessed letter
private String getPartitionKey(String s, char c) {
String word = "";
String letter = Character.toString(c);
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) == c) {
word += letter;
} else {
word += "-";
}
}

return word;
}
// update guessString with the guessed letter
private void addLetterToGuessString(StringBuilder guessString, char letter, String key) {
for(int i = 0; i < key.length(); i++) {
if(key.charAt(i) != '-') {
guessString.setCharAt(i, key.charAt(i));
}
}
}

}

最佳答案

问题在于您在迭代集合时正在修改集合。

集合是currentList,您正在partition()中迭代它。当您向此处的 tempList 添加单词时,您可以修改它:

key = getPartitionKey(word, choice);

if(wordPartitions.containsKey(key)) {
tempList = wordPartitions.get(key);
tempList.add(word);
wordPartitions.put(key, tempList);
} else {

为什么?因为之前您从 play() 调用了 updateCurrentList():

do {
choice = getUserChoice();
partition(choice);
updateCurrentList(choice);
} while (!gameOver());

并且您更新了 currentList:

String key = findLongestList();

currentList = wordPartitions.get(key);

因此,如果 getPartitionKey(word, choice) 返回的 key 与之前由 findLongestList() 返回的键相同, currentList 将与 tempList 相同,因此您将修改正在迭代的集合。

解决方案?如果 tempListcurrentList 相同,则不要向其中添加该单词(根据定义,它已经具有该单词)。所以,你可以像这样重写你的 if-else (我删除了一些无用的代码):

if(wordPartitions.containsKey(key)) {
tempList = wordPartitions.get(key);
} else {
wordPartitions.put(key, new ArrayList<String>());
}

if (tempList!=currentList) {
tempList.add(word);
}

关于java - 无法弄清楚是什么触发了 "java.util.ConcurrentModificationException",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21961975/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com