Są tu dwa problemy:
Pierwszą kwestią jest dodanie do Collection
po Iterator
zwróceniu an . Jak wspomniano, nie ma zdefiniowanego zachowania, gdy element bazowy Collection
jest modyfikowany, jak wspomniano w dokumentacji Iterator.remove
:
... Zachowanie iteratora jest nieokreślone, jeśli bazowa kolekcja zostanie zmodyfikowana, podczas gdy iteracja jest w toku w inny sposób niż wywołanie tej metody.
Druga kwestia polega na tym, że nawet jeśli Iterator
można było uzyskać a, a następnie powrócić do tego samego elementu, w którym się Iterator
znajdował, nie ma gwarancji co do kolejności iteracji, jak zaznaczono w Collection.iterator
dokumentacji metody:
... Nie ma żadnych gwarancji co do kolejności zwracania elementów (chyba że ta kolekcja jest instancją jakiejś klasy, która daje gwarancję).
Na przykład, powiedzmy, że mamy listę [1, 2, 3, 4]
.
Powiedzmy, że 5
został dodany, gdy Iterator
był w 3
, i jakoś otrzymujemy, Iterator
który może wznowić iterację od 4
. Jednak nie ma gwarancji, która 5
nastąpi później 4
. Kolejność iteracji może być taka [5, 1, 2, 3, 4]
- wtedy iterator nadal będzie pomijał element5
.
Ponieważ nie ma gwarancji zachowania, nie można zakładać, że coś wydarzy się w określony sposób.
Jedną z alternatyw może być oddzielne, Collection
do którego można dodawać nowo utworzone elementy, a następnie iterowanie po tych elementach:
Collection<String> list = Arrays.asList(new String[]{"Hello", "World!"});
Collection<String> additionalList = new ArrayList<String>();
for (String s : list) {
additionalList.add(s);
}
for (String s : additionalList) {
System.out.println(s);
}
Edytować
Opierając się na odpowiedzi Avi , możliwe jest umieszczanie w kolejce elementów, które chcemy iterować, do kolejki i usuwanie elementów, gdy kolejka zawiera elementy. Pozwoli to na „iterację” po nowych elementach oprócz elementów oryginalnych.
Spójrzmy, jak by to działało.
Koncepcyjnie, jeśli w kolejce mamy następujące elementy:
[1, 2, 3, 4]
A kiedy usuniemy 1
, zdecydujemy się dodać 42
, kolejka będzie wyglądać następująco:
[2, 3, 4, 42]
Ponieważ kolejka jest strukturą danych FIFO (pierwsze weszło , pierwsze wyszło), ta kolejność jest typowa. (Jak zauważono w dokumentacji Queue
interfejsu, nie jest to konieczne a Queue
. Weźmy przykładPriorityQueue
którym porządkuje elementy według ich naturalnego porządku, więc nie jest to FIFO).
Poniżej znajduje się przykład użycia a LinkedList
(czyli a Queue
) w celu przejścia przez wszystkie elementy wraz z dodatkowymi elementami dodanymi podczas dekolekcji. Podobnie jak w powyższym przykładzie, element 42
jest dodawany po usunięciu elementu 2
:
Queue<Integer> queue = new LinkedList<Integer>();
queue.add(1);
queue.add(2);
queue.add(3);
queue.add(4);
while (!queue.isEmpty()) {
Integer i = queue.remove();
if (i == 2)
queue.add(42);
System.out.println(i);
}
Wynik jest następujący:
1
2
3
4
42
Zgodnie z oczekiwaniami pojawił się element, 42
który został dodany po trafieniu 2
.