在嵌套的while循环中将Iterator位置重置为0

时间:2018-05-25 08:30:44

标签: java loops iterator

我正在两个列表上执行迭代。

// events and items are two lists.

Iterator<Event> eventIterator = events.iterator();
Iterator<EventItem> itemIterator = items.iterator();

while (eventIterator.hasNext()) {

    Event event = eventIterator.next();

    while (itemIterator.hasNext()) {

        EventItem item = itemIterator.next();

        if (event.getId().equals(item.getEventId())) {

            // CLAIMED
            itemIterator.remove();
        }
    }

    // PROBLEM IS HERE.

}

问题:

我将itemIterator循环到最后,如果项目被声明,我还会从itemIterator中删除这些项目。但是,当eventIterator上的下一次迭代运行时,itemIterator已经结束了。

如何在不使用itemIterator重新启动0的情况下重置items.iterator()以定位itemIterator,因为这样可以将项目从item移除以供下次迭代。

来自itemIterator的一个event只能由eventIterator中的一个itemIterator声明。因此,在声明之后将该项目保留在迭代中是没有意义的。因此,我从gradlew clean删除了该项目。

如果他们减少迭代次数而不是传统的for-each循环,我愿意接受替代方案。

2 个答案:

答案 0 :(得分:4)

  

如何在不使用itemIterator重新启动items.iterator()的情况下将itemIterator重置为0位置,因为这样可以将项目从itemIterator.remove()移除以供下次迭代。

不,它不会。 next()从您获取迭代器的集合中删除该项,而不仅仅是迭代器。如果从该集合中获得一个新的迭代器,它就不再有该项了;你删除了它。来自the JavaDoc

  

从底层集合中删除此迭代器返回的最后一个元素(可选操作)。每次调用while时,只能调用此方法一次。

(我的重点)

您无法重置迭代器;只需在Iterator<Event> eventIterator = events.iterator(); while (eventIterator.hasNext()) { Event event = eventIterator.next(); Iterator<EventItem> itemIterator = items.iterator(); while (itemIterator.hasNext()) { EventItem item = itemIterator.next(); if (event.getId().equals(item.getEventId())) { // CLAIMED itemIterator.remove(); } } // If you need to loop a second time for some reason: itemIterator = items.iterator(); // ... } 内获得一个新的。

#include <fstream>

int main()
{
    std::ofstream ("Hello.txt");
    return 0;
}

答案 1 :(得分:2)

使用像这样的嵌套循环是O(N * M)并且价格昂贵,但它也很冗长,这掩盖了你想要实现的目的。我建议你使用Java 8中的流。

// get all the event's ids
Set<String> eventIds = events.stream()
        .map(Event::getId)
        .collect(Collectors.toSet());

// remove the entries from items with a matching id.
items.removeIf(i -> eventIds.contains(i.getEventId()));

时间复杂度为O(N + M)。

  

并且,删除/声明的项目被添加到另一个列表(我称之为EventDto,数据传输对象)

你可以先建立一个列表来做到这一点。

// remove the entries from items with a matching id.
List<EventItem> toMove = items.stream()
                              .filter(i -> eventIds.contains(i.getEventId()))
                              .collect(Collectors.toList());
items.removeAll(toMove);
anotherList.addAll(toMove);

如果将id用作地图的键

,这可能会更有效

e.g。

Map<String, Event> events = ... // events keyed by id
Map<String, EventItem> items = ... // event items keys by eventId

events.keySet().removeAll(items.keySet());