代码之家  ›  专栏  ›  技术社区  ›  rupinderjeet

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

  •  0
  • rupinderjeet  · 技术社区  · 8 年前

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

    // 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 最后,也从 项迭代器 如果物品被要求赔偿。但是,当下一个迭代 eventIterator 会跑的, 项迭代器 已经结束了。

    我怎么重置 项迭代器 到位置 0 不用重新初始化 items.iterator() 因为这会使从 项迭代器 下一次迭代。

    item 项迭代器 只能由一个索赔 event 事件迭代器 。所以,在声明该项之后,将其保留在迭代中是没有意义的。因此,我从 项迭代器 .

    如果它们比传统的for each循环减少迭代次数,那么我对备选方案持开放态度。

    2 回复  |  直到 8 年前
        1
  •  4
  •   T.J. Crowder    8 年前

    我怎么重置 itemIterator 在不重新初始化0的情况下使用 items.iterator() 因为这会使从 项迭代器 下一次迭代。

    不,不会的。 itemIterator.remove() 从中删除项目 收集 迭代器来自,而不仅仅是迭代器。如果从该集合中获得一个新的迭代器,它将不再具有该项;您将其删除。从 the 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();
        // ...
    }
    
        2
  •  2
  •   Peter Lawrey    8 年前

    使用这样的嵌套循环是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());