我正在编写一个解决Mastermind游戏的程序。该程序的要点是列出所有可能的解决方案,并在每次猜测不正确之后,从列表中删除任何不至少提供该解决方案的内容。此方法用于比较两个字符串(guess和strFromArray)以查看它们是否获得相同的值。但是,我收到了一个错误,我无法弄清楚原因。任何帮助,将不胜感激。
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Game.shortenTheList(Game.java:88)
at Game.guess(Game.java:76)
at Game.play(Game.java:40)
at Game.main(Game.java:23)
/*
* Compares the two strings. If they would get the same output, return false. If they would get a different output, return true.
*/
public boolean compare(String guess, String strFromArray, int black, int white)
{
int white2 = 0;
int black2 = 0;
char[] arr1 = guess.toCharArray();
char[] arr2 = strFromArray.toCharArray();
for(int i=0; i<guess.length(); i++)
{
if(arr1[i] == arr2[i])
{
black2 ++;
arr1[i] = '$';
arr2[i] = '%';
}
}
for(int i=0; i<guess.length(); i++)
{
for(int j=0; j<strFromArray.length(); j++)
{
if(arr1[i] == arr2[j])
{
white2++;
arr1[i] = '!';
arr2[j] = '@';
}
}
}
if(black == black2 && white == white2)
return false;
else
return true;
}
/*
* Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
*/
public void shortenTheList(String guess, int black1, int white1)
{
for (String str : possibleSolutions)
{
if(compare(guess, str, black1, white1))
{
possibleSolutions.remove(str);
}
}
}
答案 0 :(得分:8)
打开Iterator
(使用for(String str: possibleSolutions)
时隐式执行此操作,除了在{{possibleSolutions
上调用remove
之外,对基础集合(Iterator
)进行任何修改1}}将导致ConcurrentModificationException
;这在集合类中非常清楚地记录。
如果您需要从集合中删除项目,请使用明确的Iterator
:
Iterator<String> it = possibleSolutions.iterator();
while(it.hasNext()) {
if(compare(guess, it.next(), black1, white1))
it.remove();
}
正如@allprog指出的那样,当你有一个明确的“过滤”问题时,功能方法会更好。在Java 8是一个选项之前,使用Guava的Iterables#filter
或Iterables#removeIf
可能是一个不错的选择;你只需要包装你的compare
方法并将其传入。
答案 1 :(得分:2)
/*
* Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
*/
public void shortenTheList(String guess, int black1, int white1)
{
for (String str : possibleSolutions)
{
if(compare(guess, str, black1, white1))
{
possibleSolutions.remove(str);
}
}
}
有你的问题。
相反,请使用:
/*
* Shortens the list of possible solutions by eliminating everything that wouldn't get at least the given output.
*/
public void shortenTheList(String guess, int black1, int white1)
{
Iterator<String> it = possibleSolutions.iterator();
while(it.hasNext())
{
String str = it.next();
if(compare(guess, str, black1, white1))
{
it.remove();
}
}
}
这是从当前正在迭代的集合中删除对象的唯一干净方法。另一种不那么优雅的方法是创建一个单独的String
列表来删除和迭代它。
答案 2 :(得分:1)
使用foreach循环迭代时,无法修改列表 possibleSolutions 。
将您的代码更改为以下内容:
public void shortenTheList(String guess, int black1, int white1)
{
for(Iterator<String> it = possibleSolutions.iterator(); it.hasNext()){
String str = it.next();
if(compare(guess, str, black1, white1)){
it.remove();
}
}
}
答案 3 :(得分:0)
如chrylis所说,如果不使用Iterator,则无法从集合中删除元素。
示例:
public void shortenTheList(String guess, int black1, int white1)
{
for (String str : possibleSolutions)
{
if(compare(guess, str, black1, white1))
{
possibleSolutions.remove(str);
}
}
}
应该是:
public void shortenTheList(String guess, int black1, int white1)
{
Iterator i = possibleSolutions.Iterator();
while(i.hasNext())
{
String str = (String) i.next();
if(compare(guess, str, black1, white1))
{
i.remove();
}
}
}