Java Stream.collect en Kotlin: guía completa con ejemplos

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Cómo dejar de escribir Stream.collect en Kotlin y empezar a vivir



¿Alguna vez has migrado de Java a Kotlin y te has sentido como un pez fuera del agua? Especialmente cuando se trataba de streams. En Java 8 estábamos acostumbrados a las cadenas .stream().filter().map().collect(). Y en Kotlin — ¡pum! — no hay Stream.collect en la forma habitual. Pero no te apresures a entrar en pánico. En realidad, en la biblioteca estándar de Kotlin está todo lo mismo, solo que más cómodo, más conciso y sin ruido innecesario.



En este artículo, analizaremos qué equivalentes de Java 8 Stream.collect existen en Kotlin y lo mostraremos con ejemplos reales. Si buscas una respuesta a la pregunta "What Java 8 Stream.collect equivalents are available in the standard Kotlin library?" — estás en el lugar correcto. Repasaremos las operaciones más populares: desde la simple recolección en una lista hasta la agrupación compleja y la unión de cadenas.



¿Listo? ¡Vamos allá!



1. El caso más simple: toList() y toSet()



En Java, para recoger el resultado de un stream en una lista, escribes:



List<String> result = list.stream()    .filter(s -> s.length() > 3)    .collect(Collectors.toList());


En Kotlin esto se convierte en una sola línea sin collect:



val result = list.filter { it.length > 3 }


Sí, no has oído mal. filter en Kotlin ya devuelve una lista. Pero si necesitas especificar explícitamente el tipo de colección, usa toList(), toSet() o toMutableList():



val numbers = listOf(1, 2, 3, 4, 5, 5)val uniqueNumbers: Set<Int> = numbers.toSet()// Resultado: [1, 2, 3, 4, 5]


Conclusión: en Kotlin, la mayoría de las operaciones con colecciones (filter, map, flatMap) devuelven inmediatamente una lista. Ya no necesitas collect(Collectors.toList()).



2. Agrupación: groupingBy en lugar de Collectors.groupingBy



La agrupación es una de las tareas más comunes. En Java se ve así:



Map<Integer, List<String>> byLength = list.stream()    .collect(Collectors.groupingBy(String::length));


En Kotlin existe la elegante función groupBy para esto:



val words = listOf("gato", "código", "gato grande", "gatito")val byLength = words.groupBy { it.length }// Resultado: {4=[gato], 6=[código], 11=[gato grande], 6=[gatito]}


Pero hay un matiz: groupBy devuelve directamente Map<K, List<V>>. ¿Y si necesitas algo más complejo, como contar el número de elementos en cada grupo? En Java usarías Collectors.counting():



Map<Integer, Long> countByLength = list.stream()    .collect(Collectors.groupingBy(String::length, Collectors.counting()));


En Kotlin para esto existe groupingBy + eachCount:



val countByLength = words.groupingBy { it.length }.eachCount()// Resultado: {4=1, 6=2, 11=1}


¿Y si necesitas recoger no una lista, sino, por ejemplo, un conjunto? Usa groupBy con transformación:



val byLengthSet = words.groupBy(keySelector = { it.length }, valueTransform = { it.uppercase() })// Resultado: {4=[GATO], 6=[CÓDIGO, GATITO], 11=[GATO GRANDE]}


Consejo: si necesitas algo intermedio entre groupBy y groupingBy, usa groupingBy — es perezoso y permite aplicar diferentes agregaciones (eachCount, fold, reduce).



3. Unión de cadenas: joinToString() en lugar de Collectors.joining()



En Java, unir cadenas con un separador:



String joined = list.stream()    .collect(Collectors.joining(", "));


En Kotlin esto se hace aún más simple:



val words = listOf("Kotlin", "Java", "Python")val joined = words.joinToString(", ")                

Blogs

Book Recommendations