scalabeginner

Mutable Collections and Buffers

Use mutable collections: ArrayBuffer, ListBuffer, mutable Map/Set, and when to choose mutable vs immutable.

scala
import scala.collection.mutable

@main def run(): Unit =
  // ArrayBuffer: like ArrayList (amortized O(1) append)
  val buf = mutable.ArrayBuffer.empty[Int]
  buf += 1
  buf += 2
  buf ++= List(3, 4, 5)
  buf.prepend(0)
  buf.insert(3, 99)  // insert at index
  println(s"Buffer: $buf")

  buf.remove(3)  // remove at index
  buf -= 5       // remove first occurrence
  println(s"After remove: $buf")

  // ListBuffer: efficient prepend and append
  val lb = mutable.ListBuffer("a", "b", "c")
  lb.prepend("z")
  lb.append("d")
  val list = lb.toList  // O(1) conversion to List
  println(s"ListBuffer: $lb")
  println(s"As List: $list")

  // Mutable Map
  val scores = mutable.Map("Alice" -> 95, "Bob" -> 87)
  scores("Carol") = 92
  scores += ("Dave" -> 88)
  scores.update("Alice", 97)
  scores.remove("Bob")
  println(s"Scores: $scores")

  // getOrElseUpdate (like computeIfAbsent)
  val cache = mutable.Map.empty[String, Int]
  val v1 = cache.getOrElseUpdate("key", { println("  Computing..."); 42 })
  val v2 = cache.getOrElseUpdate("key", { println("  Won't run"); 0 })
  println(s"Cache: $cache")

  // Mutable Set
  val tags = mutable.Set("scala", "jvm")
  tags += "fp"
  tags ++= Set("akka", "cats")
  tags -= "jvm"
  println(s"Tags: $tags")
  println(s"Contains fp: ${tags.contains("fp")}")

  // StringBuilder
  val sb = StringBuilder()
  sb.append("Hello")
  sb.append(", ")
  sb.append("World!")
  sb.insert(5, " Beautiful")
  println(s"StringBuilder: ${sb.result()}")

  // Stack (LIFO)
  val stack = mutable.Stack[Int]()
  stack.pushAll(List(1, 2, 3))
  println(s"Top: ${stack.top}")
  println(s"Pop: ${stack.pop()}")
  println(s"Stack: $stack")

  // Queue (FIFO)
  val queue = mutable.Queue[String]()
  queue.enqueueAll(List("first", "second", "third"))
  println(s"Dequeue: ${queue.dequeue()}")
  println(s"Queue: $queue")

  // PriorityQueue (max-heap by default)
  val pq = mutable.PriorityQueue(3, 1, 4, 1, 5, 9, 2, 6)
  println(s"Priority: ${pq.dequeueAll.toList}")

  // Min-heap
  val minPQ = mutable.PriorityQueue(3, 1, 4)(Ordering[Int].reverse)
  println(s"Min first: ${minPQ.dequeue()}")

  // When to use mutable:
  // 1. Performance-critical inner loops
  // 2. Building collections incrementally
  // 3. Local scope only (don't expose mutability)
  val result = locally {
    val builder = mutable.ArrayBuffer.empty[String]
    for i <- 1 to 5 do builder += s"item-$i"
    builder.toList  // return immutable
  }
  println(s"Built: $result")

Use Cases

  • Performance-critical collection building
  • Caching and memoization
  • Algorithm implementation with state

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.