2012-09-17 51 views
1
String input from keyboard 
Vector<String> myVector = new Vector<String>(someArray.length); //assume Vector is populated 
Iterator<String> itr = myVector.iterator(); 

for loop begins 
    while(itr.hasNext() && itr.next().equals(input)){ 
     itr.remove(); 
    } 

    ... 

    while(itr.hasNext() // is this the problem source? 
    run more code 

for loop ends 

噹噹前元素等於字符串input,我想刪除該元素,否則繼續迭代。我不斷收到併發異常。使用Java創建異常的迭代器故障

我還應該做什麼?我應該在其他地方移動我的itr.next嗎?

問題:我想要的邏輯,如果當前向量元素等於目標,我希望它從向量中刪除。我怎樣才能做到這一點?

+3

Vector是否與其他線程共享?是否有代碼修改您已省略的循環內的Vector內容? –

+0

你可以通過異常的完整堆棧跟蹤嗎? – kosa

+3

就像在你之前的問題中所說的那樣,你的迭代器沒有做任何有用的事情。你不需要它,把它拿出來。 –

回答

2

我不知道爲什麼你正在併發修改例外,因爲通過迭代器刪除項是合法:根據文檔,

如果Vector在創建迭代器後的任何時候在結構上被修改,以任何方式除外通過迭代器自己的刪除或添加方法,迭代器將拋出ConcurrentModificationException

要回答你的問題有關從載體去除等於目標的所有元素,最簡單的解決方法是使用VectorremoveAll方法。

myVector.removeAll(Collections.singletonList(input)); 
2

A ConcurrentModificationException可以在遍歷集合時引發,而不是小心地從中移除元素。

我建議你建立一個單獨的List以包含要移除的元素,並在循環完成執行後從原始Vector中刪除它們。

其他建議:

你也可以遍歷列表的副本。

使用foreach循環:

for (String value : myVector) { 
    ... 
} 
+3

這並非嚴格意義上的 - 使用迭代器並使用(並且僅使用)'iterator.remove()'從其中移除元素是完全合法的。例如:for(Iterator it = list.iterator(); it.hasNext();){if(someCondition)it.remove(); }' –

+0

我同意。您可以通過簡單地調用originalList.removeAll(elementsToBeRemovedList)來移除單獨列表中的所有元素;正如上面的人指出的,你可以使用iterator.remove,但要注意對於某些子類型,它會拋出一個不受支持的操作異常。我更喜歡Dan提到的方法,因爲它更容易理解......除非你的列表大小非常非常大。 – vinnybad

+0

感謝您的建議,我更新了我的答案。 –

1

你初始化向量的內容是什麼?你在構造函數中設置它的長度,但是我看不到你實際上正在向它添加字符串,這將導致NullPointerException。

你可能想使用的初始化向量:Arrays.asList(的someArray)

有一個正確的向量當,你不需要有內部的for循環

一個while循環的迭代

像這樣的東西應該工作:

String[] someArray = new String[]{ "A", "B", "C" }; 
Vector<String> myVector = new Vector<String>(Arrays.asList(someArray)); 
Iterator<String> itr = myVector.iterator(); 
while(itr.hasNext()){ 
    String myString = itr.next(); 
    if (myString.equals(input)) itr.remove(); 
} 

編輯的理由讓你得到的是很可能是因爲您沒有正確調用方法。接下來例外。 .next方法只應在每個hasNext調用後調用一次,並且.remove只應在每個調用.next後調用一次。由於您在代碼中省略了詳細信息,因此很難準確找出問題所在。但總的來說,不需要for循環。 while循環應該足夠了,但是if語句中不應該有hasNextnext

正確的方法使用迭代的迭代器(僞代碼):

while (iterator has more items) { 
    get the next item 
    do something with the item (remove it if it should be removed, or handle it in another way) 
} 
0

我只希望避免整個迭代器。 這應該做你想要什麼:

while (myVector.remove(input)) { 
    // this should get them all 
    } 
+0

這樣做嗎? – bouncingHippo

+0

它應該工作。但是dasblinkenlight的例子更好。它將獲得與輸入相等的所有內容。 –

+0

我試過你的工作!upvoting你的答案..希望你也upvote我的問題...我想如果有人發表了這個問題與你的答案,我也會解決它! – bouncingHippo

0

嘗試包裝你的載體是這樣的:

Vector vector = Collections.synchronizedCollection(vector); 

和簡短的javadoc解釋:

返回的同步(線程安全的)collection由指定集合 支持。爲了保證串行訪問,通過返回的集合完成對後備集合的所有訪問都是 的關鍵是 。

當務之急是用戶迭代它時,在返回 集合手動同步:

Collection c = 
Collections.synchronizedCollection(myCollection); 
     ... synchronized(c) { 
     Iterator i = c.iterator(); // Must be in the synchronized block 
     while (i.hasNext()) 
      foo(i.next()); } 
+0

這可以,如果你確信該矢量不是在多線程環境中(不被其他線程共享)使用來完成,因爲同步它將使鎖定使用它的所有其它線程的載體。 – dbf

+0

@dbf必須完成一些同步。在這種情況下,沒有理由不在Vector上進行。其他線程將不得不等待操作完成。 – WeMakeSoftware

+0

這並非總是需要線程需要等待,特別是如果它們已經在執行代碼中並且因爲它們不是第一個在隊列中而處於等待狀態。我有一個LPC和MBus控制器的問題,通過CAN進行通信。我只能說,它並不總是得到預期的行爲.. – dbf