2012-04-27 161 views
1

我正在迭代java.util.LinkedList,並且在某些情況下向其中添加了一個元素。將元素添加到Java LinkedList的末尾,同時迭代它

LinkedList<Schedule> queue = new LinkedList<Schedule>(schedules); 
ListIterator<Schedule> iterator = queue.listIterator(); 
while (iterator.hasNext()) { 
    Schedule schedule = iterator.next(); 
    if(condition) 
     iterator.add(new Schedule()); 
} 

的問題是,如果我開始例如一個項目,該新項目將在未來iterator.next()調用和迭代退出前加入。

如何在迭代時在LinkedList的末尾添加項目? 請不要告訴我使用另一個列表並在第一個列表之後迭代它,因爲它不能正確解決我的問題。

+1

只是好奇,你是否正式被要求不使用另一個列表? – UmNyobe 2012-04-27 11:27:14

+0

沒有明顯的,但我想迭代時添加,因爲我需要在迭代期間處理新添加的元素,這可能是最短的方式。 – 2012-04-27 13:17:42

+0

重複的https://stackoverflow.com/questions/993025/java-adding-elements-to-a-collection-during-iteration有一些很好的答案。 – 2017-11-24 16:35:44

回答

2

如果你不能使用另一個列表,你可以通過計算你通過迭代器處理的元素數量並將其與列表的原始大小進行比較來解決你的問題:所有新元素將在該列表,因此當您達到原始大小時您可以結束循環。

LinkedList<Schedule> queue = new LinkedList<Schedule>(schedules); 
int origSize = queue.size(); 
int currCount = 0; 
ListIterator<Schedule> iterator = queue.listIterator(); 
while (iterator.hasNext()) { 
    ++currCount; 
    if (currCount >= origSize) { 
    break; // reached the end of the original collection 
    } 
    Schedule schedule = iterator.next(); 
    if(condition) 
    iterator.add(new Schedule()); 
} 

你也可以使用一個額外的列表來跟蹤新的元素,並添加到原始列表後的處理結束:

LinkedList<Schedule> queue = new LinkedList<Schedule>(schedules); 
LinkedList<Schedule> addQueue = new LinkedList<Schedule>(); 
ListIterator<Schedule> iterator = queue.listIterator(); 
while (iterator.hasNext()) { 
    Schedule schedule = iterator.next(); 
    if(condition) 
    addQueue.add(new Schedule()); 
} 
queue.addAll(addQueue); 

另外,還要注意iterator.add()

將指定的元素插入列表(可選操作)。該元素緊接在下一個元素(如果有的話)和下一個元素之前(如果有)返回的下一個元素之前插入。 (如果列表不包含元素,則新元素成爲列表中的唯一元素。)新元素插入到隱式遊標之前:後續對下一個元素的調用不受影響,隨後對前一個元素的調用將返回新元素。 (這個調用由一個數值增加,將通過向nextIndex或previousIndex呼叫被退回。)

所以如果你有列表中的一個以上的元素,它不會在新添加到末尾,但是在當前的和由next()返回的之間。如果您確實想將新元素放在列表的末尾,請使用queue.add(...)

通常,在通過迭代器遍歷集合時修改集合並不可取,所以我建議您使用第二種方法(收集額外的元素在一個單獨的列表中,並將它們添加到原始結尾處)

+0

你說的是真的,但問題是我想在迭代時添加,因爲我需要在迭代期間處理新添加的元素。所以也許我必須找到使用其他列表的解決方法。 – 2012-04-27 13:14:41

+0

如果你想訪問剛插入的新元素,你可以調用'iterator.previous()'(參見答案中的引用文本) – Attila 2012-04-27 13:57:38

0

如何在LinkedList末尾附加項目,而 迭代?

public void addWork(Scheduler scheduler) 
{ 
synchronized(scheduler) 
{ 
    queue.addLast(scheduler); 
} 
} 

,您可以使用queue.removeFirst()隊列處理項目從上到向下。

public synchronized Scheduler getWork() 
{ 
    return queue.removeFirst(); 
} 

編輯。

+0

但是如果你在迭代時這樣做,你會得到一個ConcurrentModificationException異常。 – 2012-04-27 11:51:36

+0

編輯:一個單獨的同步方法可能做add/get工作。 – Bitmap 2012-04-27 12:01:48

2

假設你沒有使用一個迭代器,那麼你可以只是擱置,並通過指數「迭代」在列表,而不是硬性要求:

LinkedList<Schedule> list; 

for (int i = 0; i < list.size(); i++) { 
    final Schedule schedule = list.get(i); 
    if(condition) 
     list.add(new Schedule()); 
} 
+1

+1:但是'list.get(i)'通常對鏈表不好。 – 2012-04-27 11:52:34

+0

是的我知道,迭代時添加到列表通常是一個壞主意。但這可能是OP最接近(直接)解決方案的地方。 – Perception 2012-04-27 12:11:00

0

的要求,又能迭代添加和包括迭代中添加的項目只有在不使用迭代器進行迭代時才能滿足,因爲每次添加元素都無法重新計算迭代器的狀態。如果您接受效率較低的get方法來進行迭代,則問題很簡單。例如

LinkedList<Schedule> queue = new LinkedList<Schedule>(){{add(new Schedule());add(new Schedule());add(new Schedule());}}; 
int i = 0; 
// queue.size() is evaluated every iteration 
while (i < queue.size()) { 
    Schedule schedule = queue.get(i); 
    if(i++ % 2 == 0) 
     queue.add(new Schedule()); 
} 
System.out.println(queue.size()); 

按預期打印6個。