Te damos la bienvenida a nuestra página web, aquí hallarás la respuesta de lo que andabas buscando.
Solución:
Esto puede ser suficiente en muchos casos.
stream.findAny().isPresent()
Las otras respuestas y comentarios son correctos en el sentido de que para examinar el contenido de una transmisión, se debe agregar una operación de terminal, por lo que “consume” la transmisión. Sin embargo, se puede hacer esto y volver a convertir el resultado en una secuencia, sin almacenar en búfer todo el contenido de la secuencia. Aqui hay un par de ejemplos:
static Stream throwIfEmpty(Stream stream)
Iterator iterator = stream.iterator();
if (iterator.hasNext())
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
else
throw new NoSuchElementException("empty stream");
static Stream defaultIfEmpty(Stream stream, Supplier supplier)
Iterator iterator = stream.iterator();
if (iterator.hasNext())
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, 0), false);
else
return Stream.of(supplier.get());
Básicamente, convierte el flujo en un Iterator
para llamar hasNext()
en él, y si truegire el Iterator
volver a un Stream
. Esto es ineficiente en el sentido de que todas las operaciones subsiguientes en el flujo pasarán por el iterador. hasNext()
y next()
métodos, lo que también implica que la secuencia se procesa de manera secuencial (incluso si luego se vuelve paralela). Sin embargo, esto le permite probar la secuencia sin almacenar en búfer todos sus elementos.
Probablemente hay una manera de hacer esto usando un Spliterator
en lugar de un Iterator
. Potencialmente, esto permite que el flujo devuelto tenga las mismas características que el flujo de entrada, incluida la ejecución en paralelo.
Si puede vivir con capacidades paralelas limitadas, la siguiente solución funcionará:
private static Stream nonEmptyStream(
Stream stream, Supplier e)
Spliterator it=stream.spliterator();
return StreamSupport.stream(new Spliterator()
boolean seen;
public boolean tryAdvance(Consumer super T> action)
boolean r=it.tryAdvance(action);
if(!seen && !r) throw e.get();
seen=true;
return r;
public Spliterator trySplit() return null;
public long estimateSize() return it.estimateSize();
public int characteristics() return it.characteristics();
, false);
Aquí hay un código de ejemplo usándolo:
List l=Arrays.asList("hello", "world");
nonEmptyStream(l.stream(), ()->new RuntimeException("No strings available"))
.forEach(System.out::println);
nonEmptyStream(l.stream().filter(s->s.startsWith("x")),
()->new RuntimeException("No strings available"))
.forEach(System.out::println);
El problema con la ejecución paralela (eficiente) es que admitir la división del Spliterator
requiere una forma segura para subprocesos de notar si alguno de los fragmentos ha visto algún valor de una manera segura para subprocesos. Entonces el último de los fragmentos ejecutándose tryAdvance
tiene que darse cuenta de que es el último (y tampoco pudo avanzar) para lanzar la excepción apropiada. Así que no agregué soporte para dividir aquí.
Nos puedes añadir valor a nuestro contenido tributando tu veteranía en las observaciones.