multiple - Agrupar la secuencia Java8 sin recopilarla
java stream group by multiple fields (1)
¿Hay alguna forma en Java 8 de agrupar los elementos en java.util.stream.Stream
sin recopilarlos? Quiero que el resultado sea una Stream
nuevamente. Debido a que tengo que trabajar con una gran cantidad de datos o incluso flujos infinitos, no puedo recopilar los datos primero y transmitir el resultado de nuevo.
Todos los elementos que deben agruparse son consecutivos en la primera secuencia. Por lo tanto, me gusta mantener la evaluación de la secuencia floja.
No hay forma de hacerlo usando Stream API estándar. En general, no puede hacerlo, ya que siempre es posible que en el futuro aparezca un elemento nuevo que pertenezca a cualquiera de los grupos ya creados, por lo que no podrá pasar su grupo al análisis posterior hasta que procese toda la información.
Sin embargo, si sabe de antemano que los elementos que se agrupan están siempre adyacentes en la secuencia de entrada, puede resolver su problema utilizando bibliotecas de terceros que mejoren la API de Stream. Una de esas bibliotecas es StreamEx, que es gratis y escrito por mí. Contiene un número de operadores de "reducción parcial" que colapsan elementos adyacentes en uno solo en función de algún predicado. Por lo general, debe proporcionar un BiPredicate
que pruebe dos elementos adyacentes y devuelva verdadero si deben agruparse. Algunas de las operaciones de reducción parcial se enumeran a continuación:
-
collapse(BiPredicate)
: reemplaza cada grupo con el primer elemento del grupo. Por ejemplo,collapse(Objects::equals)
es útil para eliminar duplicados adyacentes de la secuencia. -
groupRuns(BiPredicate)
: reemplace cada grupo con la Lista de elementos de grupo (para queStreamEx<T>
se convierta enStreamEx<List<T>>
). Por ejemplo,stringStream.groupRuns((a, b) -> a.charAt(0) == b.charAt(0))
creará una secuencia de Listas de cadenas donde cada lista contiene cadenas adyacentes iniciadas con la misma letra.
Otras operaciones de reducción parcial incluyen intervalMap
, runLengths()
y así sucesivamente.
Todas las operaciones de reducción parcial son flojas, paralelas y bastante eficientes.
Tenga en cuenta que puede construir fácilmente un objeto StreamEx
partir de una StreamEx
normal de Java 8 utilizando StreamEx.of(stream)
. También hay métodos para construirlo desde array, Collection, Reader, etc. La clase StreamEx
implementa la interfaz Stream
y es 100% compatible con Stream API estándar.