Gibt es eine kurze Form der Iteration über einen stream mit Indizes in Java 8?
Gibt es eine prägnante Art und Weise zu Durchlaufen, über einen Bach, während er den Zugang zu dem index in den stream???
String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"};
List<String> nameList;
Stream<Integer> indices = intRange(1, names.length).boxed();
nameList = zip(indices, stream(names), SimpleEntry::new)
.filter(e -> e.getValue().length() <= e.getKey())
.map(Entry::getValue)
.collect(toList());
scheint eher enttäuschend im Vergleich zu den LINQ-Beispiel gegeben es
string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" };
var nameList = names.Where((c, index) => c.Length <= index + 1).ToList();
Gibt es einen kürzeren Weg?
Weiter es scheint, der Reißverschluss hat sich entweder verschoben oder entfernt worden...
Was ist
Wahrscheinlich ein
Als eine Randnotiz, Herausforderung 4 sieht besser aus (IMO) mit
Ja,
Ach ja, ein weiteres problem mit einem generic-Pair-oder Tuple-Klasse ist, dass es erfordert, dass alle primitiven geschachtelt werden.
intRange()
? Kommen noch nicht über diese Methode in Java 8, bis jetzt.Wahrscheinlich ein
IntStream.rangeClosed(x, y)
.Als eine Randnotiz, Herausforderung 4 sieht besser aus (IMO) mit
List<String> allCities = map.values().stream().flatMap(list -> list.stream()).collect(Collectors.toList());
Ja,
zip
wurde entfernt, zusammen mit experimentellen zwei-geschätzt-streams verschiedenartig genannt BiStream
oder MapStream
. Das Hauptproblem ist, dass dies effektiv zu tun Java braucht wirklich eine statisch typisierte-pair-Mädchen (oder Tupel) geben. Fehlt eins, es ist ganz einfach erstellen Sie eine generische Paar oder Tupel-Klasse-es ist schon viele Male getan-aber Sie alle löschen, um den gleichen Typ.Ach ja, ein weiteres problem mit einem generic-Pair-oder Tuple-Klasse ist, dass es erfordert, dass alle primitiven geschachtelt werden.
InformationsquelleAutor Graeme Moss | 2013-08-31
Du musst angemeldet sein, um einen Kommentar abzugeben.
Der sauberste Weg ist ein Strom von Indizes:
Die resultierende Liste enthält "Erik" nur.
Einer alternative, die sieht eher vertraut, wenn Sie verwendet werden, um for-Schleifen wäre die Aufrechterhaltung einer ad-hoc-Zähler mit ein veränderliches Objekt, zum Beispiel ein
AtomicInteger
:Beachten Sie, dass bei der letzten Methode auf einem parallelen stream brechen könnte, da der Artikel nicht unbedingt verarbeitet werden", um".
Ich entwickelte eine Lösung ähnlich der von @assylias. Zur Umgehung der Problematik mit parallelen stream @StuartMarks erwähnt, habe ich zuerst eine gegebene parallele stream-sequentielle, die Zuordnung durchzuführen und die Wiederherstellung des parallel-Staates.
public static <T> Stream<Tuple2<Integer, T>> zipWithIndex(Stream<T> stream) { final AtomicInteger index = new AtomicInteger(); final Function<T, Tuple2<Integer, T>> zipper = e -> Tuples.of(index.getAndIncrement(), e); if (stream.isParallel()) { return stream.sequential().map(zipper).parallel(); } else { return stream.map(zipper); } }
Wenn Sie denken, es löst die Frage, die Sie sollte es post als Antwort sondern als Kommentar (und der code wird besser lesbar!).
Sorry, wenn ich lese, dass der code korrekt, wird es nicht funktionieren. Sie nicht haben, können verschiedene Segmente der pipeline parallel vs sequential. Nur die Letzte von
parallel
odersequential
geehrt wird, wenn der terminal-Betrieb beginnt.Um der Gerechtigkeit Willen, "der sauberste Weg" war geklaut von @Stuart ' s Antwort.
InformationsquelleAutor assylias
Die Java 8 streams API fehlen die features zu bekommen, der index der ein stream-element sowie die Fähigkeit, zip-streams zusammen. Dies ist bedauerlich, denn es macht bestimmte Anwendungen (wie die LINQ-Herausforderungen) schwieriger, als Sie würden anders sein.
Oft gibt es workarounds, aber. In der Regel kann dies durch "fahren" den Strom mit einem integer-Bereich, und unter Ausnutzung der Tatsache, dass die ursprünglichen Elemente sind oft in einem array oder in einer Sammlung zugänglich index. Zum Beispiel, die Herausforderung 2 problem auf diese Weise gelöst werden:
Wie ich oben erwähnte, dieser nutzt die Tatsache, dass die Datenquelle (das names-array) ist direkt mit Wendeschneidplatten. Wenn es nicht, diese Technik würde nicht funktionieren.
Ich gebe zu, dass dies nicht Genüge die Absicht, die Herausforderung 2. Dennoch ist es nicht das problem lösen, halbwegs effektiv.
BEARBEITEN
Meinem vorherigen code-Beispiel verwendet
flatMap
zur Sicherung der filter und map Operationen, aber das war umständlich und lieferte keinen Vorteil. Ich habe aktualisiert die Beispiel pro den Kommentar von Holger.IntStream.range(0, names.length).filter(i->names[i].length()<=i).mapToObj(i->names[i])
? Es funktioniert ohne Boxen...Hm, ja, warum habe ich glaube, ich brauchte, um
flatMap
überhaupt?Schließlich kriegen wir das ... ich wahrscheinlich
flatMap
weil es eine Art von sicherungen eine Filter-und mapping-operation in eine einzige operation, aber das ist wirklich bietet keinen Vorteil. Ich werde Bearbeiten Sie das Beispiel.Stream.( Array ) erstellen einer stream-Schnittstelle für ein array. Effektiv, wodurch es in
Stream.of( names ).filter( n -> n.length() <= 1).collect( Collectors.toList() );
Weniger unboxing und weniger Speicher-Zuordnung; wir sind nicht die Schaffung einer Reihe stream mehr.InformationsquelleAutor Stuart Marks
Seit Guave 21, die Sie verwenden können,
Beispiel (aus offizielle doc):
InformationsquelleAutor numéro6
Habe ich die folgende Lösung in meinem Projekt. Ich denke, es ist besser als die Verwendung von mutable Objekte oder integer reicht.
StreamSupport.stream()
und eine benutzerdefinierte iterator.InformationsquelleAutor user1195526
Neben protonpack, jOOλ s Seq bietet diese Funktionalität (und durch die Erweiterung libraries, die darauf aufbauen, wie cyclops-reagieren, ich bin der Autor dieser Bibliothek).
Seq unterstützt auch nur Seq.(Namen) und bauen eine JDK-Stream unter der Decke.
Dem einfach reagieren äquivalent würden ähnlich Aussehen wie
Die einfach-version reagieren zugeschnitten für asynchrone /gleichzeitige Verarbeitung.
InformationsquelleAutor John McClean
Nur der Vollständigkeit halber hier die Lösung mit meinem StreamEx Bibliothek:
Hier erstellen wir eine
EntryStream<Integer, String>
die sichStream<Entry<Integer, String>>
und fügt einige bestimmten Operationen wiefilterKeyValue
oderWerte
. AuchtoList()
Verknüpfung verwendet wird..forEach(entry -> {})
?wenn ich verstehe, dass Sie die Frage richtig, dann ja, Sie kann schreiben
.forKeyValue((key, value) -> {})
.InformationsquelleAutor Tagir Valeev
Fand ich die Lösungen hier, wenn der Stream erstellt, der Liste oder ein array (und Sie wissen, die Größe). Aber was ist, wenn Strom mit unbekannter Größe? In diesem Fall versuchen Sie diese Variante:
Verwendung:
InformationsquelleAutor alex.b
Mit einer Liste Sie können versuchen,
Ausgabe:
Danke für die Anregung. Ich werde die änderungen.
InformationsquelleAutor V0idst4r
Gibt es nicht eine Möglichkeit zum Durchlaufen eines
Stream
während mit Zugriff auf den index, weil einStream
ist anders als alleCollection
. EinStream
ist lediglich eine pipeline für den Transport von Daten von einem Ort zu einem anderen, wie es in der Dokumentation:Keine Speicherung. Ein stream ist nicht eine Daten-Struktur, die speichert Elemente; stattdessen tragen Sie die Werte aus einer Datenquelle (die könnte eine Datenstruktur, einen generator, einen IO-Kanal usw.) über eine pipeline von Rechenoperationen.
Natürlich, wie Sie zu sein scheinen, anspielend auf Ihre Frage, konnte man immer konvertieren Sie Ihre
Stream<V>
zu einemCollection<V>
wie einList<V>
, in dem Sie haben Zugriff auf die Indizes.Ihr link auf die Dokumentation ist gebrochen.
InformationsquelleAutor Josh M
Mit https://github.com/poetix/protonpack
u kann das tun-zip:
InformationsquelleAutor 42n4
Wenn Sie nichts dagegen haben, mit einem Drittanbieter-Bibliothek, Eclipse-Sammlungen hat
zipWithIndex
undforEachWithIndex
verfügbar für die Verwendung über viele Arten. Hier ist eine Reihe von Lösungen, um diese Herausforderung für beide JDK-Typen und Eclipse Sammlungen Arten mitzipWithIndex
.Hier ist eine Lösung mit
forEachWithIndex
statt.Wenn Sie ändern die Lambda-Ausdrücke, anonyme innere Klassen, oben, dann werden alle diese code-Beispiele funktionieren in Java-5 - 7.
Hinweis: ich bin committer für Eclipse Sammlungen
InformationsquelleAutor Donald Raab
Wenn Sie geschehen, zu verwenden Vavr(früher bekannt als Javaslang), können Sie nutzen die spezielle Methode:
Wenn wir drucken die Inhalte, sehen wir etwas Interessantes:
Dies ist, weil
Streams
sind faul und wir haben keine Ahnung über die nächsten Elemente in den Bach.InformationsquelleAutor Grzegorz Piwowarek
Hier ist der code von AbacusUtil
Offenlegung: ich bin der Entwickler des AbacusUtil.
InformationsquelleAutor user_3380739
Können Sie erstellen eine statische innere Klasse zu Kapseln, die indexer als ich brauchte, um zu tun, im Beispiel unten:
InformationsquelleAutor alexpfx
Diese Frage (Stream Weg, um index des ersten Elements, das passende boolean) markiert die aktuelle Frage als Duplikat, so kann ich es nicht beantworten; ich beantworte Sie hier.
Hier ist eine generische Lösung, um die matching-index, die nicht erfordert eine externe Bibliothek.
Wenn Sie eine Liste haben.
- Und nennen es wie folgt:
Und wenn Sie eine Sammlung, versuchen Sie diese ein.
InformationsquelleAutor Steven Spungin
Wenn Sie versuchen, einen index auf ein Prädikat, versuchen Sie dies:
Wenn Sie nur Interesse an der ersten-index:
Oder wenn Sie wollen finden mehrere Indizes:
Hinzufügen
.orElse(-1);
im Fall, dass Sie wollen, um einen Wert zurückzugeben, wenn es nicht gefunden.InformationsquelleAutor live-love
Eine Möglichkeit ist die Indizierung jedes element auf der flow:
Mithilfe einer anonymen Klasse, entlang eines Baches, ist nicht gut verwendet werden, während Sie sehr nützlich.
InformationsquelleAutor Jean-Baptiste Yunès