java - Agregar nuevo valor a la secuencia existente
java-8 wildcard (5)
- Convertir corriente a lista
- agregar ítem nuevo
- Convertir de nuevo a transmisión
¿Hay una buena manera de agregar un nuevo valor a
Stream
existente?
Todo lo que puedo imaginar es algo como esto:
public <T> Stream<T> addToStream(Stream<T> stream, T elem ) {
List<T> result = stream.collect(Collectors.toList());
result.add(elem);
return result.stream();
}
Pero estoy buscando algo más conciso que pueda usar en la expresión lambda sin verbosidad.
Otra pregunta apareció cuando traté de implementar el principio PECS :
public <T> Stream<? super T> addToStream(Stream<? super T> stream, T elem ) {
List<? super T> result = stream.collect(Collectors.toList()); //error
result.add(elem);
return result.stream();
}
Parece que el comodín no funciona con
Stream.collect
y me pregunto por qué.
Gracias por adelantado.
La biblioteca
StreamEx
tiene los
#prepend()
apropiados
#prepend()
y
#append()
.
Aquí hay un ejemplo de cómo se pueden usar:
StreamEx.of("second").prepend("first").append("third").forEach(System.out::println);
Una salida es la siguiente:
first
second
third
La mejor manera es usar un flatMap de la siguiente manera:
public <T> Stream<T> appendToStream(Stream<T> stream, T element) {
return stream.flatMap(e -> Stream.of(e, element));
}
Esto opera en la secuencia original, por lo que puede ser solo otra operación intermedia en la secuencia, por ejemplo:
stream.flatMap(e -> Stream.of(e, element))
.map(...)
.filter(...)
.collect(Collectors.toList());
La pregunta oculta una suposición incorrecta: que las transmisiones realmente contienen sus datos. Ellos no; los flujos no son estructuras de datos, son un medio para especificar operaciones masivas en una variedad de fuentes de datos.
Hay combinadores para combinar dos flujos en uno, como
Stream.concat
, y fábricas para crear flujos a partir de un conjunto de elementos conocidos (
Stream.of
) o de colecciones (
Collection.stream
).
Por lo tanto, puede combinarlos si desea producir una nueva secuencia que sea la concatenación de la secuencia que tiene a mano, junto con una nueva secuencia que describa los nuevos elementos.
El problema en su ejemplo de PECS es que tiene tres ocurrencias de
? super T
? super T
, y usted supone que describen el mismo tipo, pero no lo hacen.
Cada aparición de un comodín corresponde a una captura única, que no es lo que desea;
debe darle un nombre a esa variable de tipo para que el compilador sepa que el tipo de la lista y el tipo de la secuencia de entrada son los mismos.
(Además, no materialice una colección; eso es costoso y potencialmente no termina si la transmisión no es finita. Solo use concat.) Entonces la respuesta es: simplemente se equivocaron los genéricos.
Aquí hay una forma de hacerlo:
public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) {
return Stream.concat(stream, Stream.of(element));
}
Te confundiste con PECS porque estabas pensando en "insertar" en la transmisión, cuando en realidad estás consumiendo de ella.
Qué tal si
return Stream.concat(stream, Stream.of(elem));
Esto supone que el Stream original es finito. Si no es así, puede concatenarlos en orden inverso.