I am performing iteration on two lists.
// 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.
}
Problem:
I looped through itemIterator
to the end, and also removed the items from itemIterator
if an item gets claimed. But, when next iteration on eventIterator
will run, itemIterator
is already at its end.
How can I reset itemIterator
to position 0
without reinitiating it using items.iterator()
because that will bring back items removed from itemIterator
for next iteration.
One item
from itemIterator
can only be claimed by one event
from eventIterator
. So, it doesn't make sense for me to keep that item in iteration after it is claimed. Hence, I remove the item from itemIterator
.
I am open to alternatives if they decrease the number of iterations than the traditional for-each loop.
How can I reset
itemIterator
to position 0 without reinitiating it usingitems.iterator()
because that will bring back items removed fromitemIterator
for next iteration.
No, it won't. itemIterator.remove()
removes the item from the collection you got the iterator from, not just the iterator. If you get a new iterator from that collection, it won't have that item on it anymore; you removed it. From the JavaDoc :
Removes from the underlying collection the last element returned by this iterator (optional operation). This method can be called only once per call to
next()
.
(my emphasis)
You can't reset an iterator; just get a new one, within the 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();
// ...
}
Using nested loops like this is O(N * M) and is expensive, but it's also verbose which obscures the purpose of what you are trying to achieve. I suggest you use streams from 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()));
This has a time complexity of O(N + M).
And, removed/claimed items get added to another list (I call it EventDto, data transfer object)
You can do that by building the list first.
// 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);
This might be more efficient if the id was used as the key of a map
eg
Map<String, Event> events = ... // events keyed by id
Map<String, EventItem> items = ... // event items keys by eventId
events.keySet().removeAll(items.keySet());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.