(Note: I’m currently in the process of editing this page, so there may be a few errors in the examples and formatting while I do this.)
When I wrote the Scala Cookbook, I gave each recipe my full attention. I thought that if I wrote each recipe as well as possible, and included important recipes in each chapter, well, I wanted each chapter to be worth the price of the entire book. That was my goal.
As a result of this effort — and perhaps to the chagrin of my editor — the Scala collections chapters ended up being 130 pages in length.
One of the things I tried to do in Chapters 10 and 11 is to make sense and help organize the presentation of the collections classes and methods. For instance, in one recipe on choosing a collection class, I included information like the following table, which is a subset of a larger table:

In another table I show examples of how to call each collection method. The next image shows the beginning of a table that demonstrates the methods that are available on all Traversable collection classes:

In those examples I use c to stand for collection, f to stand for a function, and p to stand for a predicate.
Categories
In another effort to help make sense of the collections methods, I broke them up into different categories of use. The following lists (and examples) show how I broke up those categories.
We’ll get to those examples in just a moment, but to show those examples we’ll first need some sample data to work with:
Sample Data
-----------
val evens = List(2, 4, 6)
val odds = List(1, 3, 5)
val a = "foo bar baz"
val foo = "foo"
val bar = "bar"
val names = List("Al", "Christina", "Kim")
val firstTen = (1 to 10).toList
val fiveToFifteen = (5 to 15).toList 
 Given that data, we can now look at the method categories along with examples of each method.
1) Filtering methods
I think of filtering methods as being those methods that filter the original collection into a subset of the original collection, without changing any of the data during the filtering process. So, a filtering method will create a subset of the original collection, without changing any of the elements with an algorithm (such as multiplying each element by two, for example). Given that definition, here is a list of filtering methods available to Scala sequential collection classes:
- distinct
- drop
- dropRight
- dropWhile
- filter
- filterNot
- find
- head
- headOption
- init
- last
- lastOption
- slice
- tail
- take
- takeRight
- takeWhile
- toSet
- withFilter
Here are examples of each of these methods:
a.distinct # "fo barz" a.drop(4) # "bar baz" a.dropRight(2) # "foo bar b" a.dropWhile(_ != ' ') # " bar baz" a.filter(_ != 'a') # "foo br bz" a.filterNot(_ != 'a') # "aa" a.filterNot(_ == 'a') # "foo br bz" firstTen.find(_ > 4) # Some(5) a.head # f a.headOption # Some(f) "foo bar".init # "foo ba" List(1,2,3).last # 3 List(1,2,3).lastOption # Some(3) a.slice(0,5) # foo b a.slice(2,9) # o bar b a.tail # oo bar baz a.take(3) # foo a.takeRight(3) # baz a.takeWhile(_ != 'r') # foo ba Seq(1,1,2,2,3,3).toSet # Set(1, 2, 3) firstTen.withFilter(_ > 5) # scala.collection.generic.FilterMonadic[Int,List[Int]] firstTen.withFilter(_ > 5).map(_ * 1) # List[Int] = List(6, 7, 8, 9, 10)
2) Transformer and reduction methods
Transformer methods take at least one input collection and apply a custom algorithm to that input collection to create a new output collection. Some of these methods can also reduce the original sequential collection down to one (or a few) derived values. These methods include:
- +
- ++
- −
- −−
- collect
- diff
- distinct
- flatMap
- map
- reverse
- sortWith
- takeWhile
- zip
- zipWithIndex
Here are examples of these collections methods:
evens ++ odds          # List(2, 4, 6, 1, 3, 5)
evens ++: odds         # List(2, 4, 6, 1, 3, 5)
0 +: evens             # List(0, 2, 4, 6)
odds :+ 7              # List(1, 3, 5, 7)
0 :: evens             # List(0, 2, 4, 6)
evens :: odds          # List(List(2, 4, 6), 1, 3, 5)
evens ::: odds         # List(2, 4, 6, 1, 3, 5)
(0 /: evens)(_ + _)    # 12
(evens :\ 0)(_ + _)    # 12
# collect and collectFirst take a partial function
firstTen.collect{case x if x % 2 == 0 => x}   # List(2, 4, 6, 8, 10)
firstTen.collectFirst{case x if x > 1 => x}   # Some(2)
a.diff("foo")                      # " bar baz"
a.distinct                         # "fo barz"
names.flatten                      # List(A, l, C, h, r, i, s, t, i, n, a, K, i, m)
names.flatMap(_.toUpperCase)       # List(A, L, C, H, R, I, S, T, I, N, A, K, I, M)
firstTen.groupBy(_ > 5)            # Map(false -> List(1, 2, 3, 4, 5), true -> List(6, 7, 8, 9, 10))
firstTen.grouped(2)                # Iterator[List[Int]] = non-empty iterator
firstTen.grouped(2).toList         # List(List(1, 2), List(3, 4), List(5, 6), List(7, 8), List(9, 10))
firstTen.grouped(5).toList         # List(List(1, 2, 3, 4, 5), List(6, 7, 8, 9, 10))
firstTen.indices                   # Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
"foo".indices                      # Range(0, 1, 2)
firstTen.intersect(fiveToFifteen)                  # List(5, 6, 7, 8, 9, 10)
a.map(_.toUpper)                   # FOO BAR BAZ
a.map(_.byteValue)                 # Vector(102, 111, 111, 32, 98, 97, 114, 32, 98, 97, 122)
a.mkString(",")                    # f,o,o, ,b,a,r, ,b,a,z
a.mkString("->", ",", "<-")        # ->f,o,o, ,b,a,r, ,b,a,z<-
a.par                              # a parallel array, ParArray(f, o, o,  , b, a, r,  , b, a, z)
a.partition(_ > 'e')               # (foorz, " ba ba")  # a Tuple2
firstTen.partition(_ > 5)          # (List(6, 7, 8, 9, 10),List(1, 2, 3, 4, 5))
a.replace('o', 'x')                # fxx bar baz
a.replace("o", "x")                # fxx bar baz
a.replaceAll("o", "x")             # fxx bar baz
a.replaceFirst("o", "x")           # fxo bar baz
firstTen.reverse                   # List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
# (more on scan, scanLeft, and scanRight below)
Seq(1,2,3,4,5).scan(1)(_ + _)         # List(1, 2, 4, 7, 11, 16)
Seq(1,2,3,4,5).scanLeft(1)(_ + _)     # List(1, 2, 4, 7, 11, 16)
Seq(1,2,3,4,5).scanRight(1)(_ + _)    # List(16, 15, 13, 10, 6, 1)
a.slice(0,5)                       # foo b
a.slice(2,9)                       # o bar b
firstTen.sliding(2)                # Iterator[List[Int]] = non-empty iterator
firstTen.sliding(2).toList         # List(List(1, 2), List(2, 3), List(3, 4), List(4, 5), List(5, 6), List(6, 7), List(7, 8), List(8, 9), List(9, 10))
firstTen.sliding(4).toList         # List(List(1, 2, 3, 4), List(2, 3, 4, 5), List(3, 4, 5, 6), List(4, 5, 6, 7), List(5, 6, 7, 8), List(6, 7, 8, 9), List(7, 8, 9, 10))
firstTen.sliding(2,2).toList       # List(List(1, 2), List(3, 4), List(5, 6), List(7, 8), List(9, 10))
firstTen.sliding(2,3).toList       # List(List(1, 2), List(4, 5), List(7, 8), List(10))
firstTen.sliding(2,4).toList       # List(List(1, 2), List(5, 6), List(9, 10))
a.sortBy                           # this is a bit long; see below
a.sortWith(_ < _)                  # "  aabbfoorz"
a.sortWith(_ > _)                  # "zroofbbaa  "
a.sorted                           # "  aabbfoorz"
firstTen.span(_ < 5)               # (List(1, 2, 3, 4),List(5, 6, 7, 8, 9, 10))
a.split(" ")                       # Array(foo, bar, baz)
a.splitAt(3)                       # (foo," bar baz")
firstTen.startsWith(Seq(1,2))      # true
a.take(3)                          # foo
a.takeRight(3)                     # baz
a.takeWhile(_ != 'r')              # foo ba
a.toArray                          # Array(f, o, o,  , b, a, r,  , b, a, z)
a.toBuffer                         # ArrayBuffer(f, o, o,  , b, a, r,  , b, a, z)
a.toList                           # List(f, o, o,  , b, a, r,  , b, a, z)
Seq(1,1,2,2,3,3).toSet             # Set(1, 2, 3)
firstTen.toStream                  # scala.collection.immutable.Stream[Int] = Stream(1, ?)
a.toLowerCase                      # foo bar baz
a.toUpperCase                      # FOO BAR BAZ
a.toVector                         # Vector(f, o, o,  , b, a, r,  , b, a, z)
a.trim                             # "foo bar baz"
evens.union(odds)                  # List(2, 4, 6, 1, 3, 5)
unzip                              # see below
Seq(1,2,3).updated(0,10)           # List(10, 2, 3)
firstTen.view                      # scala.collection.SeqView[Int,List[Int]] = SeqView(...)
a.zip(0 to 10)                                # Vector((f,10), (o,11), (o,12), ( ,13), (b,14), (a,15), (r,16), ( ,17), (b,18), (a,19), (z,20))
Seq(1,2,3).zipAll(Seq('a', 'b'), 0, 'z')      # List((1,a), (2,b), (3,z))
Seq(1,2).zipAll(Seq('a', 'b', 'c'), 0, 'z')   # List((1,a), (2,b), (0,c))
a.zipWithIndex                                # Vector((f,0), (o,1), (o,2), ( ,3), (b,4), (a,5), (r,6), ( ,7), (b,8), (a,9), (z,10))
 
 3) Sorting methods
As the name implies, sorting methods let you create a new sequence from your initial sequence, where the new sequence has been sorted:
a.sortBy # this is a bit long; see below a.sortWith(_ < _) # " aabbfoorz" a.sortWith(_ > _) # "zroofbbaa " a.sorted # " aabbfoorz"
sortBy examples
To demonstrate the sortBy method we’ll need some more complicated sample data:
case class Person(firstName: String, lastName: String)
val fred = Person("Fred", "Flintstone")
val wilma = Person("Wilma", "Flintstone")
val barney = Person("Barney", "Rubble")
val betty = Person("Betty", "Rubble")
val people = List(betty, wilma, barney, fred)
 
 Given that data, here’s a sortBy example:
people.sortBy(n => (n.lastName, n.firstName))
Here’s what a couple of examples look like in the Scala REPL:
scala> people.sortBy(n => (n.lastName, n.firstName)) res1: List[Person] = List(Person(Fred,Flintstone), Person(Wilma,Flintstone), Person(Barney,Rubble), Person(Betty,Rubble)) scala> people.sortBy(n => (n.firstName, n.lastName)) res2: List[Person] = List(Person(Barney,Rubble), Person(Betty,Rubble), Person(Fred,Flintstone), Person(Wilma,Flintstone))
4) Grouping methods
These methods let you take an existing collection and create multiple groups from that one input collection. These methods include:
- groupBy
- grouped
- partition
- sliding
- span
- splitAt
- unzip
Here are examples of these collection methods:
firstTen.groupBy(_ > 5)         # Map(false -> List(1, 2, 3, 4, 5), true -> List(6, 7, 8, 9, 10))
firstTen.grouped(2)             # Iterator[List[Int]] = non-empty iterator
firstTen.grouped(2).toList      # List(List(1, 2), List(3, 4), List(5, 6), List(7, 8), List(9, 10))
firstTen.grouped(5).toList      # List(List(1, 2, 3, 4, 5), List(6, 7, 8, 9, 10))
a.partition(_ > 'e')            # (foorz, " ba ba")  # a Tuple2
firstTen.partition(_ > 5)       # (List(6, 7, 8, 9, 10),List(1, 2, 3, 4, 5))
firstTen.sliding(2)             # Iterator[List[Int]] = non-empty iterator
firstTen.sliding(2).toList      # List(List(1, 2), List(2, 3), List(3, 4), List(4, 5), List(5, 6), List(6, 7), List(7, 8), List(8, 9), List(9, 10))
firstTen.sliding(4).toList      # List(List(1, 2, 3, 4), List(2, 3, 4, 5), List(3, 4, 5, 6), List(4, 5, 6, 7), List(5, 6, 7, 8), List(6, 7, 8, 9), List(7, 8, 9, 10))
firstTen.sliding(2,2).toList    # List(List(1, 2), List(3, 4), List(5, 6), List(7, 8), List(9, 10))
firstTen.sliding(2,3).toList    # List(List(1, 2), List(4, 5), List(7, 8), List(10))
firstTen.sliding(2,4).toList    # List(List(1, 2), List(5, 6), List(9, 10))
firstTen.span(_ < 5)            # (List(1, 2, 3, 4),List(5, 6, 7, 8, 9, 10))
a.split(" ")                    # Array(foo, bar, baz)
a.splitAt(3)                    # (foo," bar baz")
unzip                           # see below
 
 
5) Informational and mathematical methods
These methods provide information about a collection:
- canEqual
- contains
- containsSlice
- count
- endsWith
- exists
- find
- forAll
- hasDefiniteSize
- indexOf
- indexOfSlice
- indexWhere
- isDefinedAt
- isEmpty
- lastIndexOf
- lastIndexOfSlice
- lastIndexWhere
- max
- min
- nonEmpty
- product
- segmentLength
- size
- startsWith
- sum
These methods can also be used with a function you supply to obtain information about a collection:
- foldLeft
- foldRight
- reduceLeft
- reduceRight
Here are examples of these Scala collection informational methods:
a.count(_ == 'a')                  # 2
a.endsWith("baz")                  # true
evens.exists(_ > 2)                # true
firstTen.find(_ > 4)               # Some(5)
firstTen.fold(0)(_ + _)            # 55
firstTen.foldLeft(0)(_ - _)        # 55
firstTen.foldRight(0)(_ - _)       # -5
evens.forall(_ >= 2)               # true
firstTen.hasDefiniteSize           # true
firstTen.toStream.hasDefiniteSize  # false (changes to 'true' after you consume the stream)
a.indexOf('a')                     # 5
firstTen.indexOf(5)                # 4
firstTen.indexOfSlice(Seq(4,5,6))  # 3
firstTen.indexWhere(_ == 5)        # 4
firstTen.indices                   # Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
"foo".indices                      # Range(0, 1, 2)
"foo".isDefinedAt(1)               # true
"foo".isDefinedAt(3)               # false
List(1,2,3).isEmpty                # false
Nil.isEmpty                        # true
None.isEmpty                       # true
Some(1).isEmpty                    # false
a.isEmpty                          # false
a.lastIndexOf('o')                                 # 2
List(1,1,2,2,1,1,3,3).lastIndexOfSlice(Seq(1,1))   # 4
List(1,1,2,2,1,1,3,3).lastIndexWhere(_ == 1)       # 5
a.length                                           # 11
names.max                          # "Kim"
names.min                          # "Al"
a.nonEmpty                         # true
firstTen.reduce(_ + _)             # 55
firstTen.reduceLeft(_ - _)         # -53
firstTen.reduceRight(_ - _)        # Int = -5
# segmentLength
List(1,2,3,4,5,4,3,2,1).segmentLength(_ > 3, 0)   # 0
List(1,2,3,4,5,4,3,2,1).segmentLength(_ > 3, 1)   # 0
List(1,2,3,4,5,4,3,2,1).segmentLength(_ > 3, 2)   # 0
List(1,2,3,4,5,4,3,2,1).segmentLength(_ > 3, 3)   # 3
List(1,2,3,4,5,4,3,2,1).segmentLength(_ > 3, 4)   # 2
a.size                             # 11
firstTen.startsWith(Seq(1,2))      # true
 
 
6) Others
A few other methods are more difficult to categorize, including:
- flatten- converts a list of lists down to one list
- foreach- like a for loop, letting you iterate over the elements in a collection
- mkString- lets you build a String from a collection
- par- creates a parallel collection from an existing collection
- view- creates a lazy view on a collection (see Recipe 10.24)
Here are examples of some of these Scala sequential collection methods:
foo * 3                            # foofoofoo
a.diff("foo")                      # " bar baz"
names.flatten                      # List(A, l, C, h, r, i, s, t, i, n, a, K, i, m)
names.flatMap(_.toUpperCase)       # List(A, L, C, H, R, I, S, T, I, N, A, K, I, M)
a.foreach(println(_))              # prints one character per line
a.foreach(println)                 # prints one character per line
a.getBytes.foreach(println)        # prints the byte value of each character, one value per line
firstTen.intersect(fiveToFifteen)  # List(5, 6, 7, 8, 9, 10)
a.mkString(",")                    # f,o,o, ,b,a,r, ,b,a,z
a.mkString("->", ",", "<-")        # ->f,o,o, ,b,a,r, ,b,a,z<-
a.par                              # a parallel array, ParArray(f, o, o,  , b, a, r,  , b, a, z)
a.replace('o', 'x')                # fxx bar baz
a.replace("o", "x")                # fxx bar baz
a.replaceAll("o", "x")             # fxx bar baz
a.replaceFirst("o", "x")           # fxo bar baz
firstTen.reverse                   # List(10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
a.sortBy                           # this is a bit long; see below
a.sortWith(_ < _)                  # "  aabbfoorz"
a.sortWith(_ > _)                  # "zroofbbaa  "
a.sorted                           # "  aabbfoorz"
evens.union(odds)                  # List(2, 4, 6, 1, 3, 5)
Seq(1,2,3).updated(0,10)           # List(10, 2, 3)
firstTen.view                      # scala.collection.SeqView[Int,List[Int]] = SeqView(...)
firstTen.withFilter(_ > 5)                    # scala.collection.generic.FilterMonadic[Int,List[Int]]
firstTen.withFilter(_ > 5).map(_ * 1)         # List[Int] = List(6, 7, 8, 9, 10)
a.zip(0 to 10)                                # Vector((f,10), (o,11), (o,12), ( ,13), (b,14), (a,15), (r,16), ( ,17), (b,18), (a,19), (z,20))
Seq(1,2,3).zipAll(Seq('a', 'b'), 0, 'z')      # List((1,a), (2,b), (3,z))
Seq(1,2).zipAll(Seq('a', 'b', 'c'), 0, 'z')   # List((1,a), (2,b), (0,c))
a.zipWithIndex                                # Vector((f,0), (o,1), (o,2), ( ,3), (b,4), (a,5), (r,6), ( ,7), (b,8), (a,9), (z,10)) 
 | this post is sponsored by my books: | |||
|   #1 New Release |   FP Best Seller |   Learn Scala 3 |   Learn FP Fast | 
Summary
After you work with the Scala collections classes and methods for a while, many of these methods will become second nature. But when you’re first starting with Scala -- or need a quick reference on collections classes and methods you don’t use that often -- I hope that Chapters 10 and 11 in the Scala Cookbook are worth the price of the entire book.






