你应该 从来不
remove从
List时迭代。你在做什么
考虑一个简单的例子,我有一个list
{1,2,3,4,5}。让我们假设它的索引为0,我想删除所有大于3的数字。0-列表项为
1,保留
1-列表项为
2,保留
2-列表项为
3,删除。所有元素都移位了,列表现在是
{1,2,4,5}。3-列表项为
5,删除
4-列表项为 oops,不再有4
所以,我有超调的结束
List,因为我带的大小是
5当我开始迭代却成了
4之后我删除索引的元素
2,并成为
3当我在索引中删除的元素
3。
您可能会说:“啊哈,我可以通过
while循环解决此问题”:
int i = 1;while(i < teams.size()) { //do stuff}但这 更糟 :
0-列表项为
1,保留
1-列表项为
2,保留
2-列表项为
3,删除。所有元素都移位了,列表现在是
{1,2,4,5}。3-清单项目为
5,移除
因此,没有错误。看来问题已解决。但是列表包含什么?它包含
{1,2,4}。但是 4
大于
3。由于索引移位,它被跳过了。您现在有了一个更加隐蔽的错误。
如果您正在使用适当的增强型foreach循环,例如:
for(final String team : teams) { //do stuff with team}您将正确地获得一个
ConcurrentModificationException。这只是使用增强的foreach循环而不是按索引循环的众多原因之一。
为了做你想要的使用
Iterator:
final Iterator<String> iter = teams.iterator();while(iter.hasNext()) { if(iter.next().equals(testString)) iter.remove();}我将重申我的评论:
请 始终
使用Java命名约定。变量应始终位于中
camelCase。
PascalCase为课程保留。
更新
可能会更容易,因此请使用
indexOf方法在中找到团队名称
List并删除所需的元素
public void remove(final List<String> teams, final String name) { final int idx = teams.indexOf(name); if(idx < 0) throw new IllegalArgumentException("Team " + name + " not present in list."); for(int i = idx + 2; i >= idx; --i) teams.remove(i);}反向 删除这些项目非常重要
。这是由于与上述相同的问题,例如,如果删除索引处
10的项目,则位于索引处的项目
11将向下移动。因此,当您去删除索引处的项目时
11,实际上是在删除该项目,它最初是索引
12。
你可以用肮脏的把戏
for(int i = 0; i < 2; ++i) teams.remove(idx)
即继续在找到的索引处删除该项目,因为列表将向下随机排列以填补空白,您实际上将删除所需的项目以及位于其上方的两个项目。我认为这使代码很难阅读。您可能会忘记此技巧,然后返回代码,必须弄清楚它在做什么。



