Collection Views for Lazy Operations
Use collection views for efficient lazy transformations: avoid intermediate collections and improve performance.
@main def run(): Unit =
val numbers = (1 to 1_000_000).toList
// Without view: creates intermediate collections
val start1 = System.nanoTime()
val eager = numbers
.map(_ * 2)
.filter(_ % 3 == 0)
.map(_.toString)
.take(10)
val eagerTime = (System.nanoTime() - start1) / 1e6
println(f"Eager: $eagerTime%.2f ms, result: ${eager.take(3)}...")
// With view: no intermediate collections
val start2 = System.nanoTime()
val lazy_ = numbers.view
.map(_ * 2)
.filter(_ % 3 == 0)
.map(_.toString)
.take(10)
.toList
val lazyTime = (System.nanoTime() - start2) / 1e6
println(f"Lazy: $lazyTime%.2f ms, result: ${lazy_.take(3)}...")
// View on Array (no copying)
val arr = Array.tabulate(1000)(identity)
val slice = arr.view.slice(100, 200)
println(s"Slice size: ${slice.size}, first: ${slice.head}")
// Chained views
val data = (1 to 100).toVector
val pipeline = data.view
.filter(_ % 2 == 0) // keep evens
.map(n => n * n) // square
.filter(_ < 500) // under 500
.map(n => f"val=$n%04d") // format
// Only materialized when we force
println(s"Pipeline (lazy, not computed yet): ${pipeline.getClass.getSimpleName}")
val materialized = pipeline.toList
println(s"Materialized: $materialized")
// View for finding first match efficiently
val largeList = (1 to 10_000_000).toList
val found = largeList.view
.map { n =>
n * n // expensive computation
}
.find(_ > 1_000_000)
println(s"First square > 1M: $found") // stops early!
// GroupBy with view for memory efficiency
val words = "the quick brown fox jumps over the lazy brown fox".split(" ")
val grouped = words.view
.groupBy(identity)
.map((word, occurrences) => (word, occurrences.length))
.toMap
println(s"Word freq: $grouped")
// View zip (lazy)
val names = List("Alice", "Bob", "Carol", "Dave")
val scores = List(95, 87, 92, 88)
val topScorers = names.view.zip(scores.view)
.filter(_._2 >= 90)
.map((name, score) => s"$name: $score")
.toList
println(s"Top: $topScorers")Use Cases
- Memory-efficient data processing
- Short-circuit evaluation on large collections
- Pipeline optimization with lazy evaluation
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
Parallel Processing with Collections
Process data in parallel using parallel collections, Future.traverse, and batched execution.
Best for: Speeding up CPU-bound operations
Lazy Evaluation and LazyList Streams
Use lazy evaluation with LazyList for infinite sequences, memoization, and deferred computation.
Best for: Infinite sequence generation
Iterator and Lazy Operations
Use Scala iterators for memory-efficient lazy operations: transform, combine, and consume data streams.
Best for: Memory-efficient large data processing
Sequences — Lazy Evaluation for Large Data
Process large datasets efficiently with lazy sequences: generateSequence, yield, and custom iterators.
Best for: Processing large datasets without loading all into memory