在迭代它时将元素添加到Java LinkedList的末尾

时间:2012-04-27 11:14:01

标签: java iterator linked-list

我正在迭代java.util.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的末尾? 请不要告诉我使用另一个列表并在第一个列表之后重复它,因为它无法正确解决我的问题。

5 个答案:

答案 0 :(得分:1)

如果你不能使用另一个列表,你可以通过保留通过迭代器处理的元素数量的计数来解决你的问题,并将其与列表的原始大小进行比较:所有新元素都将在列表,所以你可以在达到原始大小时结束循环。

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()

  

将指定的元素插入列表(可选操作)。该元素将紧接在next将返回的下一个元素之前插入(如果有),并且在之前返回的下一个元素(如果有)之后插入。 (如果列表中不包含任何元素,则新元素将成为列表中的唯一元素。)新元素在隐式游标之前插入:对next的后续调用不受影响,后续调用previous将返回新元素。 (此调用将调用nextIndex或previousIndex返回的值增加1。)

因此,如果列表中有多个元素,则不会将新元素添加到结尾,而是添加当前元素和next()返回的元素。如果您确实要将新元素放在列表的末尾,请使用queue.add(...)

一般情况下,不建议在通过迭代器遍历它时修改集合,所以我建议你使用第二种方法(在单独的列表中收集额外的元素并在最后将它们添加到原始集合中)

答案 1 :(得分:1)

假设您没有使用迭代器的硬性要求,那么您可以将其搁置并通过索引在列表上“迭代”:

LinkedList<Schedule> list;

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

答案 2 :(得分:0)

  

如何将项目附加到LinkedList的末尾   迭代?

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

您可以使用queue.removeFirst()从上到下处理队列中的项目。

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

编辑。

答案 3 :(得分:0)

正如其他人所建议的那样,当前Collections框架在迭代过程中没有对端插入的有效,现成的支持。一个建议涉及重写迭代器。但是我说,为什么不走得更远呢?

  1. 使用反射来修改Node类的可访问性,该类为您提供了对双链接的引用,因此您无需从get(index)开始迭代,这应该用于性能代码。

  2. LinkedList继承/派生并明智地覆盖。

  3. 这是显而易见的,但出于上述2的精神,由于JDK是开源的,因此可以根据需要借用源代码并编写自己的实现。

无论哪种情况,我真的觉得该功能应该由Java LinkedList API提供。

答案 4 :(得分:-1)

只有在不使用迭代器进行迭代时,才能满足迭代中添加并在迭代中包含添加项的要求,因为每次元素都无法重新计算迭代器的状态添加。如果您接受效率较低的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个。