Czy istnieje sposób dla każdej pętli Java
for(String s : stringArray) {
doSomethingWith(s);
}
aby dowiedzieć się, jak często pętla była już przetwarzana?
Oprócz użycia starej i dobrze znanej for(int i=0; i < boundary; i++)
pętli, jest to konstrukcja
int i = 0;
for(String s : stringArray) {
doSomethingWith(s);
i++;
}
jedyny sposób, aby taki licznik był dostępny w pętli dla każdego?
Type var = null; for (var : set) dosomething; if (var != null) then ...
Odpowiedzi:
Nie, ale możesz podać własny licznik.
Powodem tego jest to, że wewnętrznie pętla dla każdego nie ma licznika; opiera się na interfejsie Iterable , tzn. wykorzystuje
Iterator
pętlę do przechodzenia przez „kolekcję” - która może wcale nie być kolekcją, i może w rzeczywistości być czymś zupełnie nie opartym na indeksach (takich jak lista połączona).źródło
for(int idx=0, String s; s : stringArray; ++idx) doSomethingWith(s, idx);
each_with_index
metoda pętliEnumerable
. Zobacz apidock.com/ruby/Enumerable/each_with_indexfor
pętli”, coś takiegofor (int i = 0; String s: stringArray; ++i)
Jest inny sposób.
Biorąc pod uwagę, że piszesz własną
Index
klasę i metodę statyczną, która zwracaIterable
ponad instancje tej klasy, możeszGdzie wdrożenie
With.index
jest podobneźródło
Najłatwiejszym rozwiązaniem jest uruchomienie własnego licznika w ten sposób:
Powodem tego jest fakt, że nie ma rzeczywistej gwarancji, że przedmioty w kolekcji (nad którymi ten wariant się
for
iteruje) mają nawet indeks lub nawet określoną kolejność (niektóre kolekcje mogą zmieniać kolejność podczas dodawania lub usuwania elementów).Zobacz na przykład następujący kod:
Po uruchomieniu możesz zobaczyć coś takiego:
wskazując, że słusznie, porządek nie jest uważany za istotną cechę zestawu.
Istnieją inne sposoby, aby to zrobić bez ręcznego licznika, ale jest to sporo pracy dla wątpliwej korzyści.
źródło
Korzystanie z lambd i interfejsów funkcjonalnych w Javie 8 umożliwia tworzenie nowych abstrakcji pętli. Mogę zapętlać kolekcję z indeksem i rozmiarem kolekcji:
Które wyjścia:
Które wdrożyłem jako:
Możliwości są nieskończone. Na przykład tworzę abstrakcję, która używa specjalnej funkcji tylko dla pierwszego elementu:
Która drukuje poprawnie listę rozdzielaną przecinkami:
Które wdrożyłem jako:
Biblioteki zaczną pojawiać się, aby robić takie rzeczy, lub możesz tworzyć własne.
źródło
Java 8 wprowadziła metodę
Iterable#forEach()
/Map#forEach()
, która jest wydajniejsza dla wielu implementacjiCollection
/ wMap
porównaniu z „klasyczną” dla każdej pętli. Jednak również w tym przypadku nie podano indeksu. Sztuką jest użycieAtomicInteger
poza wyrażeniem lambda. Uwaga: zmienne użyte w wyrażeniu lambda muszą być faktycznie ostateczne, dlatego nie możemy użyć zwykłegoint
.źródło
Obawiam się, że nie jest to możliwe
foreach
. Ale mogę zasugerować ci proste pętle w starym stylu :Zauważ, że interfejs listy daje dostęp do
it.nextIndex()
.(edytować)
Do zmienionego przykładu:
źródło
Jedną z
Sun
rozważanych zmian jestJava7
zapewnienie dostępu do wewnętrznejIterator
pętli foreach. składnia będzie mniej więcej taka (jeśli zostanie to zaakceptowane):Jest to cukier składniowy, ale najwyraźniej zgłoszono wiele żądań dotyczących tej funkcji. Ale dopóki nie zostanie zatwierdzony, będziesz musiał sam policzyć iteracje lub użyć zwykłej pętli for z
Iterator
.źródło
Rozwiązanie idiomatyczne:
źródło
Chociaż istnieje tak wiele innych sposobów osiągnięcia tego samego, podzielę się swoją drogą dla niektórych niezadowolonych użytkowników. Korzystam z funkcji IntStream Java 8.
1. Tablice
2. Lista
źródło
Jeśli potrzebujesz licznika w pętli dla każdego, musisz liczyć sam. O ile mi wiadomo, nie ma wbudowanego licznika.
źródło
Istnieje „wariant” odpowiedzi na pax… ;-)
źródło
i=0; i++;
podejściem?W sytuacjach, gdy potrzebuję indeksu tylko od czasu do czasu, np. W klauzuli catch, czasami używam indexOf.
źródło
Najlepszym i zoptymalizowanym rozwiązaniem jest wykonanie następujących czynności:
Gdzie Typ może być dowolnym typem danych, a typami jest zmienna, o którą ubiegasz się o pętlę.
źródło
Jestem trochę zaskoczony, nikt nie sugerował, co następuje (przyznaję, że jest to leniwe podejście ...); Jeśli stringArray jest pewnego rodzaju Listą, możesz użyć czegoś takiego jak stringArray.indexOf (S), aby zwrócić wartość dla bieżącej liczby.
Uwaga: zakłada to, że elementy Listy są unikalne lub że nie ma znaczenia, czy nie są one unikalne (ponieważ w takim przypadku zwróci indeks pierwszej znalezionej kopii).
Są sytuacje, w których byłoby to wystarczające ...
źródło
Oto przykład tego, jak to zrobiłem. Otrzymuje indeks dla każdej pętli. Mam nadzieję że to pomoże.
źródło