为什么这个循环不工作?

时间:2014-09-24 14:27:51

标签: java for-loop

所以我必须创建一个名为mylistofstrings的类,它听起来就像是一个字符串数组。我必须编写的方法之一是retain all方法,它只保留列表中与作为参数输入的字符串相等的字符串。 for循环似乎跳过它应该删除的一半,任何想法为什么? size方法只返回列表中的元素数量,并且易于发布。

public boolean retain(String string) {
     if (string == null) {
        throw new NullPointerException();
     }
     MyListOfStrings temp= new MyListOfStrings(this);
     int t=this.size();
     for (int i=0;i<this.size;i++){
         if (string.equals(temp.get(i))!=true){
             this.remove(i);
         }
     }
     return t<this.size();

这是get方法:

public String get(int index) {
    if (index < 0 || index >= size) {
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    return strings[index];
}

和删除方法:

public String remove(int index) {
    if (index < 0 || index >= size) {
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
    String temp = strings[index]; // Save to return at end
    System.arraycopy(strings, index + 1, strings, index, size - index - 1);
    strings[size - 1] = null;
    size--;
    return temp;
}

5 个答案:

答案 0 :(得分:3)

在迭代数组时,您正在更改数组的内容。当移除位置x处的项目时,位置x + 1处的项目将获得新位置x,但由于循环已经访问过x,因此下一次迭代将是位置x + 1,而现在持有位置的项目x将被跳过。

您需要执行以下所示的操作:removing items from list in java

即。实施Iterable,并使用Iterator

删除项目

答案 1 :(得分:1)

一旦您开始更改其中一个容器,它们将不再平行,因此您无法删除正确的元素。

你可以这样做:

int i = 0;
while (i < this.size) {
    if (!string.equals(strings[i])) {
         remove(i);
    } else {
         ++i;
    }
}

请注意,当您移除元素i时,以下元素会向下移动,而下一个元素现在位于i位置,因此如果您增加i,您将会超过它

答案 2 :(得分:0)

您不应在迭代期间调用编辑操作。考虑一下这个清单:

1: "1"
2: "2"
3: "3"
4: "4"

现在您要保留"1"并开始迭代:

第一步:

1: "1" <- do nothing
2: "2"
3: "3"
4: "4"

第二步

1: "1"
2: "2" <- remove
3: "3"
4: "4"

结果将是

1: "1"
2: "3"
3: "4"

第三步

1: "1"
2: "3"
3: "4" <- remove

最终结果

1: "1"
2: "3"

即使你的临时列表也是如此,因为索引仍在递增。在第3步中,您可以与临时列表中的"3"进行比较,但请从实际列表中删除"4"

答案 3 :(得分:0)

看起来像这一行 -

 MyListOfStrings temp= new MyListOfStrings(this);

正在复制输入列表的引用,而不是创建重复列表。

结果,您正在删除当前条目,然后跳过下一个条目(现在是当前条目),因为新对象引用了相同的基础数据。

您可以创建要删除的索引列表,然后在循环结束时删除它们。当然,您应该以相反的顺序删除以防止发生同样的问题。

答案 4 :(得分:0)

要在迭代时从列表中删除对象,最好为列表使用/实现Iterator。

但是如果你想在没有Iterator的情况下这样做,你可以通过每次从列表中删除字符串时将i-Variable减少1来实现:

 for (int i=0;i<this.size;i++){
     if (string.equals(temp.get(i))!=true){
         this.remove(i);
         i--;
     }
 }

这是必需的,因为您将i + 1-Element复制到您需要再次检查的i-Position。