Scala’s collection classes begin with the Traversable
and Iterable
traits, and extend into the three main categories of sequences (Seq), sets (Set), and maps (Map). Sequences further branch off into indexed and linear sequences.
The Traversable
trait lets you traverse an entire collection, and its Scaladoc states that it “implements the behavior common to all collections in terms of a foreach
method,” which lets you traverse the collection repeatedly.
The Iterable
trait yields an Iterator
that can be used as:
val coll = ... // some collection
val iter = coll.iter
while(iter.hasNext)
doSomething(iter.next())
When using an iterator, the collection can be traversed only once, because each element is consumed during the iteration process.
Seq
is an ordered sequence of values:IndexSeq
indicates that reandom access of elements is efficient through index. By default,IndexSeq
creates aVector
.LinearSeq
implis that the collection can be efficiently split into head and tail. By default,LinearSeq
creates aList
, which is a singly linked list.Set
is an unordered collection of values.Map
is a set of (key, value) pairs.
Scala prefers immutable collections: companion objects in scala.collection
package produce immutable collections. And Predef
object (which is always imported) has alias to immutable List
, Set
and Map
.
Best practice: to use both immutable and mutable collection, import scala.collection.mutable
and you can get Map
and immutable map and mutable.Map
as mutable.
Work with immutable collections: you can create new collections out of old ones.
coll ++ coll2
and coll ++: coll2
returns a collection of the same type with all elements combined.
For mutable collections:
coll += elem
,coll -= elem
: add or removeelem
tocoll
.coll += (e1, e2, ...)
,coll -= (e1, e2, ...)
: add or remove elements tocoll
.coll ++= coll2
,coll --= coll2
: add or removecoll2
tocoll
.
Strict and lazy collections
A transformer method is a method that constructs a new collection from an existing collection. This includes methods like map
, filter
, reverse
, etc. — any method that transforms the input collection to a new output collection. Given that definition, collections can also be thought of in terms of being strict or lazy.
In a strict collection, memory for the elements is allocated immediately, and all of its elements are immediately evaluated when a transformer method is invoked.
In a lazy collection, memory for the elements is not allocated immediately, and transformer methods do not construct new elements until they are demanded. All of the collection classes except Stream are strict, but the other collection classes can be converted to a lazy collection by creating a view on the collection.
Common Methods
map
: applies the one-to-one function to all elements of a collection, and return a new collection.take
andtakeRight
: select first or lastn
elements.drop
anddropRight
: select all elements except first or lastn
.flatMap
: if an element of a collection is a collection, treat its elements as in the outer collection and apply the function on to them directly. For example,Option
is a collection with 0 or 1 element, so flapMap will only apply to those match toSome()
.foreach
: similar tomap
but it doesn’t return a value.filter
: yields all elements of a collection taht matches a condition.reduceLeft
: takes a binary function, and applies to all elements of a sequence from left to right. For example,(1 to 100).reduceLeft(_ + _)
sums all numbers from 1 to 100. In
_ + _
each underscore represents a separate parameter.sortWith
: takes a binary comparison function for sorting./:
: Apply a binary operator to a start value and all elements of this traversable or iterator, from left to right.:\
does the same from right to left. Note the order of parameters for this binary operator.
def removeAll(collection: TraversableOnce[A], items: Iterable[A]) = (collection /: items) { (coll, item) => coll.remove(item) }
def addAll(collection: TraversableOnce[A], items: Iterable[A]) = (items :\ collection) { (item, coll) => coll.add(item) }
Tuple
Tuple is a set of values, up to 22, enclosed in parentheses. Underlying they are instances of Tuple1 to Tuple22 classes. To access its components, using _1
, _2
, etc. Note it starts from 1.
(a, b)
and (a -> b)
both produce a Tuple2
. However, latter form is easier to read.
Tuples are usually for multiple assignments: val (first, second, third) = t
. It can be useful when a function or method returns multiple values. Unnecessary components are marked out with _
placeholder.
zip method
zip
bundles elements in two collections into a sequence of tuples. If one collection is longer than the other, the remaining is ignored.zipAll
fills the shorter collection with default value.zipped
, available on 2- and 3-tuple of lists, does 2- or 3-way zip of multiple lists.zipWithIndex
converts a list into a list of(elem, index)
pairs. Note the index is the second element in the tuple.
Option
A generic type to hold some optional information. It can be matched to Some(a)
or None
. It’s better than null
check. You can think of it as an iterable that holds either zero or one values, so you can use foreach
to perform an operation if it is not empty.
Either
Either[A, B]
is more general than Option[A]
’s Some()
/None
pair. To get the concrete type, match against Left(A)
and Right(B)
.