Collections
## Learning Objectives
- Master Scala collection hierarchy
- Work with List, Set, Map, Array
- Understand immutable vs mutable collections
- Use common collection operations
- Work with Option
## Collection Hierarchy
```text
Traversable
├── Iterable
│ ├── Seq
│ │ ├── List, Vector, Array, ArrayBuffer
│ │ ├── Range
│ │ └── Queue, Stack
│ ├── Set
│ │ ├── HashSet, LinkedHashSet, TreeSet
│ │ └── BitSet
│ └── Map
│ ├── HashMap, LinkedHashMap, TreeMap
│ └── ListMap
```
## List
### Creating Lists
```scala
val fruits = List("apple", "banana", "cherry")
val numbers = List(1, 2, 3, 4, 5)
val empty = List()
// Cons operator
val head :: rest = numbers
// head: 1, rest: List(2, 3, 4, 5)
// Constructing with ::
val newList = 0 :: numbers // List(0, 1, 2, 3, 4, 5)
val combined = 1 :: 2 :: 3 :: Nil // List(1, 2, 3)
```
### List Operations
```scala
val list = List(1, 2, 3, 4, 5)
list.head // 1
list.tail // List(2, 3, 4, 5)
list.last // 5
list.init // List(1, 2, 3, 4)
list.length // 5
list.isEmpty // false
// Concatenation
List(1, 2) ::: List(3, 4) // List(1, 2, 3, 4)
List.concat(List(1, 2), List(3, 4)) // Same
// Reverse
list.reverse // List(5, 4, 3, 2, 1)
```
## Set
### Creating Sets
```scala
val colors = Set("red", "green", "blue")
val numbers = Set(1, 2, 3, 3, 3) // Duplicates removed: Set(1, 2, 3)
val empty = Set()
```
### Set Operations
```scala
val set = Set(1, 2, 3, 4, 5)
set.contains(3) // true
set(3) // true (same as contains)
set + 6 // Set(1, 2, 3, 4, 5, 6)
set - 3 // Set(1, 2, 4, 5)
set ++ Set(6, 7) // Set(1, 2, 3, 4, 5, 6, 7)
set -- Set(3, 4) // Set(1, 2, 5)
// Set operations
val set1 = Set(1, 2, 3)
val set2 = Set(3, 4, 5)
set1 union set2 // Set(1, 2, 3, 4, 5)
set1 intersect set2 // Set(3)
set1 diff set2 // Set(1, 2)
```
## Map
### Creating Maps
```scala
val ages = Map("Alice" -> 30, "Bob" -> 25)
val kv = Map(("Alice", 30), ("Bob", 25))
val empty = Map[String, Int]()
// Mutable map
import scala.collection.mutable
val mutableMap = mutable.Map("x" -> 1, "y" -> 2)
```
### Map Operations
```scala
val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
map("a") // 1 (throws if not found)
map.get("a") // Some(1)
map.getOrElse("d", 0) // 0
map.keys // Iterable(a, b, c)
map.values // Iterable(1, 2, 3)
map.contains("b") // true
// Update (creates new map for immutable)
val updated = map + ("d" -> 4) // Map(a -> 1, b -> 2, c -> 3, d -> 4)
val removed = map - "b" // Map(a -> 1, c -> 3)
```
## Array
### Creating Arrays
```scala
val arr = Array(1, 2, 3, 4, 5)
val arr2 = new Array[Int](5) // Array of 5 zeros
val arr3 = Array.fill(3)("hello") // Array("hello", "hello", "hello")
val arr4 = Array.range(1, 5) // Array(1, 2, 3, 4)
```
### Array Operations
```scala
val arr = Array(1, 2, 3, 4, 5)
arr(0) // 1 (update: arr(0) = 10)
arr.length // 5
arr.toList // List(1, 2, 3, 4, 5)
// Arrays are mutable
arr(0) = 10
arr.update(1, 20)
```
## Immutable vs Mutable
### Immutable Collections (Default)
```scala
import scala.collection.immutable._
val list = List(1, 2, 3)
val newList = list :+ 4 // List(1, 2, 3, 4) - original unchanged
val map = Map("a" -> 1)
val newMap = map + ("b" -> 2) // Map("a" -> 1, "b" -> 2)
```
### Mutable Collections
```scala
import scala.collection.mutable._
val buffer = ListBuffer[Int]()
buffer += 1
buffer += 2
buffer ++= List(3, 4, 5)
buffer.remove(0)
buffer.toList // List(2, 3, 4, 5)
val mutableMap = mutable.Map[String, Int]()
mutableMap("a") = 1
mutableMap.put("b", 2)
mutableMap.remove("a")
```
## Common Operations
### map
```scala
List(1, 2, 3).map(x => x * 2) // List(2, 4, 6)
List(1, 2, 3).map(_ * 2) // List(2, 4, 6)
Set(1, 2, 3).map(x => x * 2) // Set(2, 4, 6)
```
### filter
```scala
List(1, 2, 3, 4, 5).filter(x => x > 2) // List(3, 4, 5)
List(1, 2, 3, 4, 5).filter(_ > 2) // List(3, 4, 5)
```
### flatMap
```scala
List(List(1, 2), List(3, 4)).flatMap(x => x) // List(1, 2, 3, 4)
def getWords(line: String): List[String] = line.split(" ").toList
List("Hello world", "Scala is fun").flatMap(getWords)
// List(Hello, world, Scala, is, fun)
```
### reduce
```scala
List(1, 2, 3, 4, 5).reduce((a, b) => a + b) // 15
List(1, 2, 3, 4, 5).reduce(_ + _) // 15
List(1, 2, 3, 4, 5).reduceLeft(_ + _) // 15
// With initial value
List(1, 2, 3).fold(10)(_ + _) // 16
```
### flatten
```scala
List(List(1, 2), List(3, 4)).flatten // List(1, 2, 3, 4)
```
### Collect
```scala
List(1, 2, 3, 4, 5).collect {
case x if x % 2 == 0 => x * 2
} // List(4, 8)
```
### Group By
```scala
List(1, 2, 3, 4, 5, 6).groupBy(x => x % 2)
// Map(0 -> List(2, 4, 6), 1 -> List(1, 3, 5))
```
### Take, Drop, SplitAt
```scala
val list = List(1, 2, 3, 4, 5)
list.take(3) // List(1, 2, 3)
list.drop(3) // List(4, 5)
list.splitAt(3) // (List(1, 2, 3), List(4, 5))
list.takeWhile(_ <= 3) // List(1, 2, 3)
list.dropWhile(_ <= 3) // List(4, 5)
```
### Sort
```scala
List(3, 1, 4, 1, 5, 9).sorted // List(1, 1, 3, 4, 5, 9)
List(3, 1, 4, 1, 5, 9).sortWith(_ < _) // List(1, 1, 3, 4, 5, 9)
case class Person(name: String, age: Int)
val people = List(Person("Bob", 30), Person("Alice", 25))
people.sortBy(_.name) // Sort by name
people.sortBy(_.age) // Sort by age
```
## Range
```scala
val r = 1 to 10 // Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val r2 = 1 until 10 // Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
val r3 = 1 to 10 by 2 // Range(1, 3, 5, 7, 9)
val r4 = 10 to 1 by -2 // Range(10, 8, 6, 4, 2)
```
## Option
Option represents optional values:
```scala
val someValue: Option[Int] = Some(5)
val noValue: Option[Int] = None
// Pattern matching
someValue match {
case Some(x) => println(s"Got value: $x")
case None => println("No value")
}
// Safe retrieval
val map = Map("a" -> 1)
map.get("a") // Some(1)
map.get("b") // None
map.getOrElse("c", 0) // 0
// Map on Option
someValue.map(_ * 2) // Some(10)
noValue.map(_ * 2) // None
// FlatMap on Option
someValue.flatMap(x => if (x > 0) Some(x * 2) else None) // Some(10)
```
## Views and Lazy Collections
```scala
val nums = (1 to 1000000).view
// Operations are lazy - no intermediate collections
val result = nums.map(_ * 2).filter(_ > 100).take(5).toList
// For very large collections
val largeView = (1 to BigInt(999999999)).view
```
## Summary
- Scala has immutable (default) and mutable collections
- List is a singly-linked list, efficient at prepending
- Set stores unique elements
- Map stores key-value pairs
- Array is mutable with fixed size
- Common operations: map, filter, flatMap, reduce, fold
- Option represents optional values (Some or None)
- Views provide lazy evaluation for large collections
- Prefer immutable collections for safer, more predictable code
Comments
Comments powered by Giscus
To enable comments, add your Giscus embed code here.
Learn more about Giscus →