Java Stream.collect in Kotlin: Complete Guide with Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

How to Stop Writing Stream.collect in Kotlin and Start Living



Have you ever switched from Java to Kotlin and felt like a fish out of water? Especially when it came to streams. In Java 8, we got used to chains like .stream().filter().map().collect(). And in Kotlin — bam! — there's no Stream.collect in its familiar form. But don't panic. In fact, the standard Kotlin library has all the same things, only more convenient, concise, and without unnecessary noise.



In this article, we'll break down what analogs of Java 8 Stream.collect exist in Kotlin, and show them with real examples. If you're looking for an answer to the question "What Java 8 Stream.collect equivalents are available in the standard Kotlin library?" — you've come to the right place. We'll go through the most popular operations: from simple collection into a list to complex grouping and string joining.



Ready? Let's go!



1. The Simplest Case: toList() and toSet()



In Java, to collect a stream result into a list, you write:



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


In Kotlin, this turns into one line without collect:



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


Yes, you heard that right. filter in Kotlin already returns a list. But if you need to explicitly specify the collection type, use toList(), toSet(), or toMutableList():



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


Conclusion: In Kotlin, most collection operations (filter, map, flatMap) immediately return a list. collect(Collectors.toList()) is no longer needed.



2. Grouping: groupingBy Instead of Collectors.groupingBy



Grouping is one of the most common tasks. In Java, it looks like this:



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


In Kotlin, there's an elegant function groupBy for this:



val words = listOf("cat", "code", "kettle", "kitten")val byLength = words.groupBy { it.length }// Result: {3=[cat, code], 6=[kettle], 6=[kitten]}


But there's a nuance: groupBy immediately returns Map<K, List<V>>. What if you need something more complex, like counting the number of elements in each group? In Java, you would use Collectors.counting():



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


In Kotlin, there's groupingBy + eachCount for this:



val countByLength = words.groupingBy { it.length }.eachCount()// Result: {3=2, 6=2}


And if you need to collect not a list but, say, a set? Use groupBy with transformation:



val byLengthSet = words.groupBy(keySelector = { it.length }, valueTransform = { it.uppercase() })// Result: {3=[CAT, CODE], 6=[KETTLE, KITTEN]}


Tip: If you need something between groupBy and groupingBy, use groupingBy — it's lazy and allows applying different aggregations (eachCount, fold, reduce).



3. Joining Strings: joinToString() Instead of Collectors.joining()



In Java, joining strings with a delimiter:



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


In Kotlin, it's even simpler:



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

Blogs

Book Recommendations