Looking for kotlin Answers? Try Ask4KnowledgeBase
Looking for kotlin Keywords? Try Ask4Keywords

KotlinEquivalentes de flujo de Java 8


Introducción

Kotlin proporciona muchos métodos de extensión en colecciones e iterables para aplicar operaciones de estilo funcional. Un tipo de Sequence dedicado permite la composición perezosa de varias de estas operaciones.

Observaciones

Sobre la pereza

Si desea procesar de forma perezosa una cadena, puede convertirla a una Sequence utilizando asSequence() antes de la cadena. Al final de la cadena de funciones, normalmente también terminas con una Sequence . Luego puede usar toList() , toSet() , toMap() o alguna otra función para materializar la Sequence al final.

// switch to and from lazy
val someList = items.asSequence().filter { ... }.take(10).map { ... }.toList()

// switch to lazy, but sorted() brings us out again at the end
val someList = items.asSequence().filter { ... }.take(10).map { ... }.sorted()

¿Por qué no hay tipos?

Notará que los ejemplos de Kotlin no especifican los tipos. Esto se debe a que Kotlin tiene inferencia de tipo completo y es completamente seguro en el momento de la compilación. Más que Java porque también tiene tipos anulables y puede ayudar a prevenir el temido NPE. Así que esto en Kotlin:

val someList = people.filter { it.age <= 30 }.map { it.name }

es lo mismo que:

val someList: List<String> = people.filter { it.age <= 30 }.map { it.name }

Debido a que Kotlin sabe qué es la people , y que people.age es Int por lo tanto, la expresión de filtro solo permite la comparación con un Int , y que people.name es una String por lo tanto, el paso del map produce una List<String> ( List de String de solo lectura).

Ahora, si las people posiblemente fueran null , como en una List<People>? entonces:

val someList = people?.filter { it.age <= 30 }?.map { it.name }

Devuelve una List<String>? eso tendría que estar marcado con un valor nulo ( o usar uno de los otros operadores de Kotlin para valores que aceptan valores nulos , vea esta forma idiomática de Kotlin para tratar los valores que aceptan valores nulos y también la forma idiomática de manejar una lista vacía o nula en Kotlin )

Reutilizando corrientes

En Kotlin, depende del tipo de colección si se puede consumir más de una vez. Una Sequence genera un nuevo iterador cada vez y, a menos que afirme "usar solo una vez", se puede restablecer al inicio cada vez que se actúe. Por lo tanto, mientras lo siguiente falla en la secuencia de Java 8, pero funciona en Kotlin:

// Java:
Stream<String> stream =
Stream.of("d2", "a2", "b1", "b3", "c").filter(s -> s.startsWith("b"));

stream.anyMatch(s -> true);    // ok
stream.noneMatch(s -> true);   // exception
// Kotlin:  
val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }

stream.forEach(::println) // b1, b2

println("Any B ${stream.any { it.startsWith('b') }}") // Any B true
println("Any C ${stream.any { it.startsWith('c') }}") // Any C false

stream.forEach(::println) // b1, b2

Y en Java para obtener el mismo comportamiento:

// Java:
Supplier<Stream<String>> streamSupplier =
    () -> Stream.of("d2", "a2", "b1", "b3", "c")
          .filter(s -> s.startsWith("a"));

streamSupplier.get().anyMatch(s -> true);   // ok
streamSupplier.get().noneMatch(s -> true);  // ok

Por lo tanto, en Kotlin, el proveedor de los datos decide si se puede restablecer y proporcionar un nuevo iterador o no. Pero si desea restringir intencionalmente una Sequence a una iteración de tiempo, puede usar la función constrainOnce() para la Sequence siguiente manera:

val stream = listOf("d2", "a2", "b1", "b3", "c").asSequence().filter { it.startsWith('b' ) }
        .constrainOnce()

stream.forEach(::println) // b1, b2
stream.forEach(::println) // Error:java.lang.IllegalStateException: This sequence can be consumed only once. 

Ver también:

Equivalentes de flujo de Java 8 Ejemplos relacionados