在嵌套的 while 循环中将迭代器位置重置为 0



我正在对两个列表进行迭代。

// 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已经结束了。

如何在不使用items.iterator()重新启动itemIterator来定位0,因为这将从itemIterator中删除的项目恢复为下一次迭代。

来自itemIterator的一个item只能由eventIterator的一个event认领。因此,在声明该项目后将其保留为迭代对我来说是没有意义的。因此,我从itemIterator中删除了该项目。

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

如何在不使用items.iterator()重新启动itemIterator的情况下将重置为位置 0,因为这将从itemIterator中删除的项目恢复为下一次迭代。

不,不会。itemIterator.remove()从获取迭代器的集合中删除该项,而不仅仅是迭代器。如果从该集合中获得新的迭代器,它将不再包含该项;你删除了它。来自JavaDoc:

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

(我的强调(

你不能重置迭代器;只需在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();
// ...
}

使用这样的嵌套循环是 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 用作地图的键,这可能会更有效

例如

Map<String, Event> events = ... // events keyed by id
Map<String, EventItem> items = ... // event items keys by eventId
events.keySet().removeAll(items.keySet());

最新更新