¿Hay alguna razón por la que hay varias formas de hacer lo mismo en Kotlin?
val viaSequence = items.asSequence() .filter { it%2 == 0 } .map { it*2 } .toList() println(viaSequence) val viaIterable = items.asIterable() .filter { it%2 == 0 } .map { it*2 } .toList() println(viaIterable) val viaStream = items.stream() .filter { it%2 == 0 } .map { it*2 } .toList() println(viaStream)Sé que el siguiente código crea una lista en cada paso, lo que agrega carga al GC y, como tal, debe evitarse:
items.filter { it%2 == 0 }.map { it*2 }Una de sus tres variantes es lo mismo que usar la Lista en sí:
items.asIterable() .filter { it%2 == 0 } Aquí, está llamando exactamente a la misma función de filter que si solo llamara a items.filter . La lista en sí misma es Iterable , por lo que se llama al filtro iterable. Este filtro examina todos los elementos disponibles y devuelve una lista completa.
Entonces, la pregunta es por qué tenemos flujos y secuencias.
Los flujos son parte de Java. Muchas de las operaciones de terminal producen Optional . Otras operaciones, como toList() , producirán tipos de plataforma no seguros para valores NULL como List<Integer!> . Por otro lado, las secuencias son nativas de Kotlin y se pueden usar con las funciones de seguridad nula en tiempo de compilación propias de Kotlin. Además, las secuencias están disponibles en variantes de Kotlin que no son JVM.
Los diseñadores de Kotlin probablemente tuvieron que crear una nueva clase, porque si solo hubieran agregado nuevas operaciones a Stream, por ejemplo, como funciones de extensión, chocarían con los nombres existentes (por ejemplo max() devuelve Optional en Java, y eso no es ideal para Kotlin, pero elegir un nombre que no sea el nombre natural max tampoco sería ideal).
Entonces, en la mayoría de los casos, debe preferir las secuencias, ya que son más idiomáticas de Kotlin. Sin embargo, hay algunas cosas que Java Streams puede hacer que aún no están disponibles para las secuencias (por ejemplo, SummaryStatistics u operaciones paralelas). Cuando necesita una operación que solo está disponible en Streams, pero tiene una Sequence, puede convertir la Sequence a Stream usando asStream() (así como viceversa).
Otra ventaja de Streams es que puede usar flujos primitivos como IntStream, para evitar el encajonado/desencuadrado innecesario.
Los flujos provienen de Java, donde no hay funciones en línea, por lo que los flujos son la única forma de usar estas cadenas funcionales en una colección en Java. Kotlin puede hacerlos directamente en Iterables, lo que es mejor para el rendimiento en muchos casos porque no es necesario crear objetos Stream intermedios.
Kotlin tiene Sequences como alternativa a Streams con estas ventajas:
Sequence.groupBy con Stream.collect ).sequence le permite crear una secuencia perezosa complicada de elementos con una sintaxis secuencial simple en una rutina. Muy poderoso.La otra respuesta menciona las ventajas que tiene Streams.