0
0
Kotlinprogramming~5 mins

Java streams vs Kotlin sequences

Choose your learning style9 modes available
Introduction

Java streams and Kotlin sequences help process collections of data step-by-step without writing loops. They make code cleaner and easier to read.

When you want to process a list of items like filtering or transforming them.
When you want to avoid writing long loops and nested conditions.
When you want to handle large data efficiently without creating many intermediate collections.
When you want to chain multiple operations on data in a clear way.
When you want lazy evaluation to improve performance.
Syntax
Kotlin
Java Stream example:
List<String> names = List.of("Anna", "Bob", "Cathy");
names.stream()
    .filter(name -> name.startsWith("A"))
    .map(String::toUpperCase)
    .forEach(System.out::println);

Kotlin Sequence example:
val names = listOf("Anna", "Bob", "Cathy")
names.asSequence()
    .filter { it.startsWith("A") }
    .map { it.uppercase() }
    .forEach { println(it) }

Java streams use stream() to start processing collections.

Kotlin sequences use asSequence() to enable lazy operations.

Examples
This filters even numbers and doubles them, then collects results back to a list.
Kotlin
val numbers = listOf(1, 2, 3, 4, 5)

// Kotlin sequence example
val result = numbers.asSequence()
    .filter { it % 2 == 0 }
    .map { it * 2 }
    .toList()

println(result)
Java stream does the same: filters even numbers, doubles them, and collects to a list.
Kotlin
List<Integer> numbers = List.of(1, 2, 3, 4, 5);

// Java stream example
List<Integer> result = numbers.stream()
    .filter(n -> n % 2 == 0)
    .map(n -> n * 2)
    .toList();

System.out.println(result);
Shows that mapping happens only when toList() is called, demonstrating lazy evaluation.
Kotlin
val names = listOf("Anna", "Bob", "Cathy")

// Kotlin sequence lazy evaluation
val seq = names.asSequence()
    .map {
        println("Mapping $it")
        it.uppercase()
    }

println("Before terminal operation")
seq.toList()
Java streams also evaluate lazily, mapping runs only when terminal operation toList() is called.
Kotlin
List<String> names = List.of("Anna", "Bob", "Cathy");

// Java stream lazy evaluation
Stream<String> stream = names.stream()
    .map(name -> {
        System.out.println("Mapping " + name);
        return name.toUpperCase();
    });

System.out.println("Before terminal operation");
stream.toList();
Sample Program

This program filters names starting with 'A' and converts them to uppercase using Kotlin sequences and Java streams (simulated in Kotlin). Both produce the same result.

Kotlin
fun main() {
    val names = listOf("Anna", "Bob", "Cathy", "Alex")

    println("Kotlin Sequence Result:")
    val kotlinResult = names.asSequence()
        .filter { it.startsWith("A") }
        .map { it.uppercase() }
        .toList()
    println(kotlinResult)

    println("Java Stream Result:")
    // Simulating Java stream in Kotlin for demonstration
    val javaResult = names.stream()
        .filter { it.startsWith("A") }
        .map { it.uppercase() }
        .toList()
    println(javaResult)
}
OutputSuccess
Important Notes

Both Java streams and Kotlin sequences support lazy evaluation, meaning operations run only when needed.

Kotlin sequences are similar to Java streams but integrate more naturally with Kotlin collections.

Use sequences or streams when working with large data to improve performance by avoiding unnecessary intermediate collections.

Summary

Java streams and Kotlin sequences help process collections step-by-step in a readable way.

Both support lazy evaluation to improve performance.

Kotlin sequences fit naturally with Kotlin code, while Java streams are standard in Java.