2014-09-24 61 views
1

所以我必須創建一個名爲mylistofstrings的類,它聽起來像一串字符串。我必須寫的一種方法是保留所有方法,它只保留列表中與作爲參數輸入的字符串相同的字符串。 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]; 
} 

和remove方法:

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; 
} 
+0

可能的重複[使用For循環從ArrayList中刪除數據](http://stackoverflow.com/questions/10738634/delete-data-from-arraylist-with-a-for-loop) – 2014-09-24 14:33:05

回答

3

您正在改變數組的內容,同時遍歷它。當移除位置x處的項目時,位置x + 1處的項目將獲得新的位置x,但是由於循環已經訪問了x,下一次迭代將位置x + 1,並且現在保存位置的項目x將被跳過。

你需要做的是這樣所示:removing items from list in java

即執行Iterable,並使用Iterator來刪除項目

+0

但是,我通過製作新的臨時類並迭代它來解決這個問題? – trosy 2014-09-24 14:32:53

+0

不,因爲您在臨時文件和實際文件中都使用相同的索引。一旦一個元素被移除,這些將不同步(因此,臨時索引x不一定與索引x相同) – Tobb 2014-09-24 14:35:28

+0

正如我在我的回答中提到的,我認爲誤解是OP認爲'新的MyListOfStrings(this)'創建了列表的一個副本,而實際上它並沒有。我們需要看到'MyListOfStrings'的構造函數來確認。 – 2014-09-24 14:42:29

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" 

即使你templist這是因爲該指數仍遞增的情況。在第3步中,您可以將您的templist中的"3"與您的實際列表中的"4"相比較。

1

一旦你開始改變你的一個容器,它們就不再平行了,所以你沒有刪除正確的元素。

你可以做這樣的:

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

注意,當您刪除元素i,以下元素下移,現在下一個元素是在i位置,所以如果你增加i你會經過它。

0

看起來這行 -

MyListOfStrings temp= new MyListOfStrings(this); 

被複制輸入列表中的參考,而不是創建一個副本列表。

因此,您將刪除當前條目,然後跳過下一個條目(現在是當前條目),因爲新對象引用了相同的基礎數據。

你可以創建一個索引列表來刪除,然後在循環結束時刪除它們。當然,您應該以相反的順序移除以防止發生同樣的問題。

0

對於從列表中移除對象的同時迭代它,最好爲您的列表使用/實現Iterator。

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

,因爲你複製這是必要的:

但是,如果你想這樣做,沒有一個迭代器,你可以通過每次1降低了I-變量,你從列表中刪除一個字符串做i + 1元素到你知道需要再次檢查的i-Position。