Scala 2.13 delivers a new collection library, for historical reasons it is also known as "collection - strawman". The refactoring of the library pursued a few main goals, such as fixing common gotchas of the previous version, simplifying its implementation and internal structure, as well as usage and backward-compatibility, achieving better integration with lazy collections and java streams and cleaner API separation between mutable and immutable collections, improving performance, and, last but not least, minimizing the migration effort from Scala 2.12's collections.
As a result, we have a library that is mostly source-compatible with the previous version, has many old methods and types (such as Traversable, TraversableOnce, and Stream) deprecated, and has a simpler internal hierarchy.
This book assumes that the reader has a rudimentary understanding of Scala collections. With this assumption, the next section will take a holistic approach and focus on giving a consistent overview of the new collection framework.
The next diagram represents the top-level hierarchy of the collection library:
Here and further, we will pretend to always have import scala.collections._ in the scope and use the following colour encoding in our diagrams:
Each of the traits describes the structure, the essence of the collection. As the name suggests, IterableOnce can be iterated over only one time. Iterable softens this constraint so that it is possible to iterate over the collection multiple times. Seq adds a notion of succession to the elements of the collection, Set adds a constraint of the uniqueness of its elements, and Map changes the type of the collection from a single element, A, to a pair of key, K, and value, V.
As mentioned, in the spirit of the separation of concerns, these traits cover only the structural characteristics. The operations defined for the specific type are placed in the helper traits carrying the Ops suffix in the name. These traits form a hierarchical structure similar to the previous one, as shown here:
Where the "normal" traits had only one type parameter, the type of the element, the Ops have three of them. In addition to the type of the element, A, the C type describes the specific representation type of the collection this trait is mixed into and thus to the return type of the first-order methods defined on this collection. The CC type refers to the representation type that can be returned by the higher-order methods, or the type constructor. We will see later in this chapter how this works in practice.
Because the inheritance tree is structured as it is, IterableOps and IterableOnceOps are effectively mixed into every collection implementation in the library. Three traits on the bottom just add some more methods, unique to the specific collection type, and override some of the definitions for efficiency. Both Iterable*Ops traits define more than a hundred of methods and they are the reason the Scala collection library is very consistent and homogenous.
Because of the importance of IterableOnceOps and IterableOps, we will take a detailed look at them in the next section. After that, we will explore the unique features of the specialized collections.