2つのリストで反復処理を実行しています。
// 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
から削除されたアイテムを戻すからです次の反復のため。
1つの
item
itemIterator
から1人の
event
のみが要求できます
eventIterator
から
。そのため、要求された後にそのアイテムを繰り返し保持するのは意味がありません。したがって、
itemIterator
からアイテムを削除します
。
従来のfor-eachループよりも反復回数が減る場合、私は代替案を受け入れています。
回答 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)の時間の複雑さがあります。
And, removed/claimed items get added to another list (I call it EventDto, data transfer object)
最初にリストを作成することでそれを行うことができます。
// 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());
いいえ、できません。
itemIterator.remove()
からアイテムを削除しますコレクション イテレータだけでなく、イテレータを取得しました。そのコレクションから新しいイテレータを取得すると、そのアイテムはそのイテレータに含まれなくなります。削除しました。 JavaDocから:(私の強調)
イテレータをリセットすることはできません。
while
内で新しいものを取得するだけです 。