该计划的目的是从文本文件中删除某些运动队及其成员,然后用新的值集覆盖原始文件。这是通过将值读入数组,然后循环遍历数组并删除团队名称和接下来的2行来尝试的,但由于某种原因,它会在索引之后停止通过数组。
我被卡住了,所以任何帮助都会很棒
代码:
private void RemoveSportsTeamButtonActionPerformed(java.awt.event.ActionEvent evt) {
String ChosenTeam = "";
ChosenTeam = JOptionPane.showInputDialog("What Team Do you want to remove?");
ArrayList<String> Teamlist = new ArrayList<String>();
if (ChosenTeam.length() > 0) {
} else {
Scanner Reader = null;
try {
Reader = new Scanner(new File("ListofSportTeams.txt"));
} catch (FileNotFoundException ex) {
}
while (Reader.hasNext()) {
Teamlist.add(Reader.next());
}
Reader.close();
for (int count = 0; count < Teamlist.size(); count++) {
{
if (Teamlist.get(count).equals(ChosenTeam)) {
Teamlist.remove(count);
Teamlist.remove(count + 1);
Teamlist.remove(count + 2);
}
}
}
}
}
SportTeamList.txt =
Team1
Jeff
James
Team2
Steve
Peter
答案 0 :(得分:2)
迭代时,您应该从remove
永远 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
但是在我删除索引{{1}后的元素后它变为4
当我删除索引2
处的元素时,它变为3
。
你可能会说,“啊哈,我可以通过3
循环解决这个问题:”
while
但这更糟:
0 - 列出项目为int i = 1;
while(i < teams.size()) {
//do stuff
}
,保留
1 - 列表项为1
,保持
2 - 列表项为2
,删除。所有元素都会移动,列表现在是3
3 - 列表项为{1,2,4,5}
,删除
所以,没有错误。看起来问题已修复。但是这个清单包含什么?它包含5
。但 {1,2,4}
大于4
。由于指数转移,它被跳过了。你现在有一个更加阴险的错误。
如果您正在使用适当的增强型foreach循环,请执行以下操作:
3
你可以正确地获得for(final String team : teams) {
//do stuff with team
}
。这只是使用增强型foreach循环而不是按索引循环的众多原因之一。
为了做你想做的事,请使用ConcurrentModificationException
:
Iterator
我将重申我的评论:
请始终使用Java naming conventions。变量应始终位于final Iterator<String> iter = teams.iterator();
while(iter.hasNext()) {
if(iter.next().equals(testString))
iter.remove();
}
。 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
即。继续删除找到的索引处的项目,因为列表将向下移动以填补您将实际删除所需项目及其上方的两个项目的差距。我认为这使得代码很难阅读。您可能会忘记这个技巧然后回到代码中并且必须弄清楚它正在做什么。
答案 1 :(得分:2)
现在,我正在使用两个列表。一个是原始的,另一个是删除列表。我阅读原始列表,如果条目以“团队”开头(如果您有其他逻辑用于区分团队名称和成员名称,请添加),我将其添加到删除列表以及以下条目,直到下一个团队名称被保留被发现。最后,我从原始列表中删除所有删除条目。
public class ListRemovalDemo
{
public static void main(String[] args)
{
List<String> teamList = new ArrayList<String>();
teamList.add("TeamName1");
teamList.add("Member1Team1");
teamList.add("Member2Team1");
teamList.add("TeamName2");
teamList.add("Member1Team2");
teamList.add("Member2Team2");
teamList.add("TeamName3");
teamList.add("Member1Team3");
teamList.add("Member2Team3");
List<String> removalList = new ArrayList<String>();
String teamToRemove = "TeamName2";
Iterator<String> teamListIterator = teamList.listIterator();
String entry;
while(teamListIterator.hasNext())
{
entry = teamListIterator.next();
if(entry.equals(teamToRemove))
{
removalList.add(entry);
if(teamListIterator.hasNext())
{
entry = teamListIterator.next();
while(!entry.startsWith("Team"))
{
removalList.add(entry);
if(teamListIterator.hasNext())
entry = teamListIterator.next();
else
break;
}
}
}
}
teamList.removeAll(removalList);
System.out.println("After removal of " + teamToRemove + ":\n" + teamList);
}
}
输出
After removal of TeamName2:
[TeamName1, Member1Team1, Member2Team1, TeamName3, Member1Team3, Member2Team3]