Tengo el siguiente código:
Stream<String> lines = reader.lines();
Si la cadena del primer puño es igual "email"
, quiero eliminar la primera cadena del flujo. Para otras cadenas de la secuencia, no necesito esta verificación.
¿Cómo podría lograrlo?
PD
Claro que puedo transformarlo en la lista, luego usar la vieja escuela para el bucle, pero además necesito transmitir nuevamente.
java
java-stream
java-11
gstackoverflow
fuente
fuente
skip(long n)
que omite los primerosn
elementos, pero no sé si puede condicionarlo de alguna manera ...stream.dropWhile(s -> s.equals("email"));
Respuestas:
Si bien el lector estará en un estado no especificado después de que construyó una secuencia de líneas a partir de él, está en un estado bien definido antes de hacerlo.
Entonces puedes hacer
Cuál es la solución más limpia en mi opinión. Tenga en cuenta que esto no es lo mismo que Java 9
dropWhile
, que dejaría caer más de una línea si coinciden.fuente
Si no puede tener la lista y debe hacerlo solo con a
Stream
, puede hacerlo con una variable.La cuestión es que solo puede usar una variable si es "final" o "efectivamente final", por lo que no puede usar un booleano literal. Aún puedes hacerlo con un
AtomicBoolean
:Nota: No me gusta usar "variables externas"
Stream
porque los efectos secundarios son una mala práctica en el paradigma de programación funcional. Mejores opciones son bienvenidas.fuente
compareAndSet
es una forma muy elegante de configurar y obtener la bandera al mismo tiempo, agradable.stream.filter(!first.compareAndSet(true, false) || !s.equals("email"))
aunque discutible.predicate
debe ser apátridaAtomicBoolean
aquí es para atender flujos paralelos (comocompareAndSet
sugiere el uso de ), entonces esto es completamente incorrecto, ya que solo funcionará si el flujo es secuencial. Sin embargo, si utiliza la técnica constream.sequential().filter(...)
, estoy de acuerdo en que funcionará.Para evitar verificar la condición en cada línea del archivo, simplemente leía y verificaba la primera línea por separado, luego ejecutaba la tubería en el resto de las líneas sin verificar la condición:
Más simple en Java 9+:
fuente
Stream.ofNullable(first).filter(not("email"::equals))
La respuesta de @Arnouds es correcta. Puede crear una secuencia para la primera línea y luego compararla a continuación,
fuente
limit(0)
seguramente debería serlimit(1)
....limit(0).filter(line -> !line.startsWith("email"))
no tiene sentido. El predicado nunca será evaluado. Para una fuente de flujo capaz de reproducir flujos, la combinación delimit(1)
en el primero yskip(1)
en el segundo sería correcta. Para una fuente de transmisión como un lector,limit(1)
nilimit(0)
funcionará. Acabas de cambiar qué línea se traga incondicionalmente. Incluso si encuentra una combinación que resulta hacer lo deseado, sería sobre la base de un comportamiento no especificado, dependiente de la implementación.Para filtrar elementos en función de su índice, puede usarlo
AtomicInteger
para almacenar e incrementar el índice mientras procesaStream
:Este enfoque permite filtrar elementos en cualquier índice, no solo en el primero.
fuente
Un poco más enrevesado, obteniendo un poco de inspiración de este fragmento .
Puede crear un
Stream<Integer>
que represente índices y "comprimirlo" con suStream<String>
para crear unStream<Pair<String, Integer>>
Luego filtre usando el índice y vuelva a asignarlo a un
Stream<String>
fuente
Aquí hay un ejemplo con
Collectors.reducing
. Pero al final crea una lista de todos modos.fuente
Prueba esto:
fuente