Ich habe folgenden Code:
Stream<String> lines = reader.lines();
Wenn die erste Zeichenfolge gleich ist, "email"
möchte ich die erste Zeichenfolge aus dem Stream entfernen. Für andere Strings aus dem Stream brauche ich diese Prüfung nicht.
Wie könnte ich es erreichen?
PS
Sicher kann ich es in die Liste umwandeln und dann die alte Schule für die Schleife verwenden, aber weiter brauche ich wieder Stream.
java
java-stream
java-11
gstackoverflow
quelle
quelle
skip(long n)
dass die erstenn
Elementestream.dropWhile(s -> s.equals("email"));
Antworten:
Während sich der Leser in einem nicht spezifizierten Zustand befindet, nachdem Sie einen Zeilenstrom daraus erstellt haben, befindet er sich in einem genau definierten Zustand, bevor Sie dies tun.
So können Sie tun
Welches ist die sauberste Lösung meiner Meinung nach. Beachten Sie, dass dies nicht mit Java 9 identisch ist
dropWhile
, bei dem mehr als eine Zeile gelöscht wird, wenn sie übereinstimmen.quelle
Wenn Sie die Liste nicht haben können und es nur mit einem tun müssen
Stream
mit a ausführen , können Sie sie mit einer Variablen ausführen.Die Sache ist, dass Sie eine Variable nur verwenden können, wenn sie "final" oder "effektiv final" ist, sodass Sie keinen wörtlichen Booleschen Wert verwenden können. Sie können es immer noch mit einem
AtomicBoolean
:Hinweis: Ich mag es nicht, "externe Variablen" in einem zu verwenden,
Stream
da Nebenwirkungen eine schlechte Praxis im Paradigma der funktionalen Programmierung sind. Bessere Optionen sind willkommen.quelle
compareAndSet
ist eine sehr elegante Art, die Flagge gleichzeitig zu setzen und zu erhalten, schön.stream.filter(!first.compareAndSet(true, false) || !s.equals("email"))
umstritten sein.predicate
muss staatenlos seinAtomicBoolean
hier für parallele Streams vorgesehen ist (wie die Verwendung voncompareAndSet
nahe legt), ist dies völlig falsch, da es nur funktioniert, wenn der Stream sequentiell ist. Wenn Sie die Technikstream.sequential().filter(...)
jedoch verwenden, stimme ich zu, dass sie funktionieren wird.Um zu vermeiden, dass die Bedingung in jeder Zeile der Datei überprüft wird, habe ich einfach die erste Zeile separat gelesen und überprüft und dann die Pipeline in den restlichen Zeilen ausgeführt, ohne die Bedingung zu überprüfen:
Einfacher auf Java 9+:
quelle
Stream.ofNullable(first).filter(not("email"::equals))
@ Arnouds Antwort ist richtig. Sie können einen Stream für die erste Zeile erstellen und dann wie folgt vergleichen:
quelle
limit(0)
sicherlichlimit(1)
….limit(0).filter(line -> !line.startsWith("email"))
macht keinen Sinn. Das Prädikat wird niemals ausgewertet. Für eine Stream-Quelle, die Streams reproduzieren kann, wäre die Kombination vonlimit(1)
der ersten undskip(1)
der zweiten korrekt. Für eine Stream-Quelle wie einen Reader funktioniert wederlimit(1)
nochlimit(0)
. Sie haben gerade geändert, welche Leitung bedingungslos verschluckt wird. Selbst wenn Sie eine Kombination gefunden hätten, die zufällig das Gewünschte tut, würde dies auf einem nicht spezifizierten, implementierungsabhängigen Verhalten beruhen.Um Elemente basierend auf ihrem Index zu filtern, können Sie den Index
AtomicInteger
speichern und erhöhen, während Sie Folgendes verarbeitenStream
:Dieser Ansatz ermöglicht das Filtern von Elementen an jedem Index, nicht nur am ersten.
quelle
Etwas komplizierter, um sich von diesem Ausschnitt inspirieren zu lassen .
Sie können eine erstellen
Stream<Integer>
, die Indizes darstellt, und diese mit Ihrer "komprimieren"Stream<String>
, um ein zu erstellenStream<Pair<String, Integer>>
Filtern Sie dann anhand des Index und ordnen Sie ihn wieder a zu
Stream<String>
quelle
Hier ist ein Beispiel mit
Collectors.reducing
. Aber am Ende wird trotzdem eine Liste erstellt.quelle
Versuche dies:
quelle