diff --git a/_overviews/collections-2.13/introduction.md b/_overviews/collections-2.13/introduction.md index 7341e31ff5..2e4d5f8abb 100644 --- a/_overviews/collections-2.13/introduction.md +++ b/_overviews/collections-2.13/introduction.md @@ -12,7 +12,7 @@ permalink: /overviews/collections-2.13/:title.html --- The collections framework is the heart of the Scala 2.13 standard -library. It provides a common, uniform, and all-encompassing +library, also used in Scala 3.x. It provides a common, uniform, and all-encompassing framework for collection types. This framework enables you to work with data in memory at a high level, with the basic building blocks of a program being whole collections, instead of individual elements. @@ -70,12 +70,18 @@ for arrays. **Example:** Here's one line of code that demonstrates many of the advantages of Scala's collections. - val (minors, adults) = people partition (_.age < 18) +{% tabs introduction_1 %} +{% tab 'Scala 2 and 3' for=introduction_1 %} +``` +val (minors, adults) = people partition (_.age < 18) +``` +{% endtab %} +{% endtabs %} It's immediately clear what this operation does: It partitions a collection of `people` into `minors` and `adults` depending on their age. Because the `partition` method is defined in the root -collection type `TraversableLike`, this code works for any kind of +collection type `IterableOps`, this code works for any kind of collection, including arrays. The resulting `minors` and `adults` collections will be of the same type as the `people` collection. diff --git a/_overviews/collections-2.13/overview.md b/_overviews/collections-2.13/overview.md index 4d739156ac..e148e0493b 100644 --- a/_overviews/collections-2.13/overview.md +++ b/_overviews/collections-2.13/overview.md @@ -13,7 +13,7 @@ permalink: /overviews/collections-2.13/:title.html --- Scala collections systematically distinguish between mutable and -immutable collections. A _mutable_ collection can be updated or +immutable collections. A _mutable_ collection can be updated, reduced or extended in place. This means you can change, add, or remove elements of a collection as a side effect. _Immutable_ collections, by contrast, never change. You have still operations that simulate @@ -43,7 +43,7 @@ A collection in package `scala.collection` can be either mutable or immutable. For instance, [collection.IndexedSeq\[T\]](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/IndexedSeq.html) is a superclass of both [collection.immutable.IndexedSeq\[T\]](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html) and -[collection.mutable.IndexedSeq\[T\]](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/IndexedSeq.html) +[collection.mutable.IndexedSeq\[T\]](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/IndexedSeq.html). Generally, the root collections in package `scala.collection` support transformation operations affecting the whole collection, the immutable @@ -73,7 +73,13 @@ A useful convention if you want to use both mutable and immutable versions of collections is to import just the package `collection.mutable`. - import scala.collection.mutable +{% tabs overview_1 %} +{% tab 'Scala 2 and 3' for=overview_1 %} +```scala mdoc +import scala.collection.mutable +``` +{% endtab %} +{% endtabs %} Then a word like `Set` without a prefix still refers to an immutable collection, whereas `mutable.Set` refers to the mutable counterpart. @@ -86,10 +92,16 @@ aliases in the `scala` package, so you can use them by their simple names without needing an import. An example is the `List` type, which can be accessed alternatively as - scala.collection.immutable.List // that's where it is defined - scala.List // via the alias in the scala package - List // because scala._ - // is always automatically imported +{% tabs overview_2 %} +{% tab 'Scala 2 and 3' for=overview_2 %} +```scala mdoc +scala.collection.immutable.List // that's where it is defined +scala.List // via the alias in the scala package +List // because scala._ + // is always automatically imported +``` +{% endtab %} +{% endtabs %} Other types aliased are [Iterable](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterable.html), [Seq](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Seq.html), [IndexedSeq](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/IndexedSeq.html), [Iterator](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/Iterator.html), [LazyList](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/LazyList.html), [Vector](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Vector.html), [StringBuilder](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/mutable/StringBuilder.html), and [Range](https://www.scala-lang.org/api/{{ site.scala-version }}/scala/collection/immutable/Range.html). @@ -116,27 +128,45 @@ Legend: The most important collection classes are shown in the figures above. There is quite a bit of commonality shared by all these classes. For instance, every kind of collection can be created by the same uniform syntax, writing the collection class name followed by its elements: - Iterable("x", "y", "z") - Map("x" -> 24, "y" -> 25, "z" -> 26) - Set(Color.red, Color.green, Color.blue) - SortedSet("hello", "world") - Buffer(x, y, z) - IndexedSeq(1.0, 2.0) - LinearSeq(a, b, c) +{% tabs overview_3 %} +{% tab 'Scala 2 and 3' for=overview_3 %} +```scala +Iterable("x", "y", "z") +Map("x" -> 24, "y" -> 25, "z" -> 26) +Set(Color.red, Color.green, Color.blue) +SortedSet("hello", "world") +Buffer(x, y, z) +IndexedSeq(1.0, 2.0) +LinearSeq(a, b, c) +``` +{% endtab %} +{% endtabs %} The same principle also applies for specific collection implementations, such as: - List(1, 2, 3) - HashMap("x" -> 24, "y" -> 25, "z" -> 26) +{% tabs overview_4 %} +{% tab 'Scala 2 and 3' for=overview_4 %} +```scala +List(1, 2, 3) +HashMap("x" -> 24, "y" -> 25, "z" -> 26) +``` +{% endtab %} +{% endtabs %} All these collections get displayed with `toString` in the same way they are written above. All collections support the API provided by `Iterable`, but specialize types wherever this makes sense. For instance the `map` method in class `Iterable` returns another `Iterable` as its result. But this result type is overridden in subclasses. For instance, calling `map` on a `List` yields again a `List`, calling it on a `Set` yields again a `Set` and so on. - scala> List(1, 2, 3) map (_ + 1) - res0: List[Int] = List(2, 3, 4) - scala> Set(1, 2, 3) map (_ * 2) - res0: Set[Int] = Set(2, 4, 6) +{% tabs overview_5 %} +{% tab 'Scala 2 and 3' for=overview_5 %} +``` +scala> List(1, 2, 3) map (_ + 1) +res0: List[Int] = List(2, 3, 4) +scala> Set(1, 2, 3) map (_ * 2) +res0: Set[Int] = Set(2, 4, 6) +``` +{% endtab %} +{% endtabs %} This behavior which is implemented everywhere in the collections libraries is called the _uniform return type principle_. diff --git a/_overviews/collections-2.13/seqs.md b/_overviews/collections-2.13/seqs.md index 712f28002f..4123b59fb1 100644 --- a/_overviews/collections-2.13/seqs.md +++ b/_overviews/collections-2.13/seqs.md @@ -16,7 +16,7 @@ The [Seq](https://www.scala-lang.org/api/current/scala/collection/Seq.html) trai The operations on sequences, summarized in the table below, fall into the following categories: -* **Indexing and length** operations `apply`, `isDefinedAt`, `length`, `indices`, and `lengthCompare`. For a `Seq`, the `apply` operation means indexing; hence a sequence of type `Seq[T]` is a partial function that takes an `Int` argument (an index) and which yields a sequence element of type `T`. In other words `Seq[T]` extends `PartialFunction[Int, T]`. The elements of a sequence are indexed from zero up to the `length` of the sequence minus one. The `length` method on sequences is an alias of the `size` method of general collections. The `lengthCompare` method allows you to compare the lengths of a sequences with an Int even if the sequences has infinite length. +* **Indexing and length** operations `apply`, `isDefinedAt`, `length`, `indices`, and `lengthCompare`. For a `Seq`, the `apply` operation means indexing; hence a sequence of type `Seq[T]` is a partial function that takes an `Int` argument (an index) and which yields a sequence element of type `T`. In other words `Seq[T]` extends `PartialFunction[Int, T]`. The elements of a sequence are indexed from zero up to the `length` of the sequence minus one. The `length` method on sequences is an alias of the `size` method of general collections. The `lengthCompare` method allows you to compare the lengths of a sequences with an Int or with an `Iterable` even if the sequences has infinite length. * **Index search operations** `indexOf`, `lastIndexOf`, `indexOfSlice`, `lastIndexOfSlice`, `indexWhere`, `lastIndexWhere`, `segmentLength`, which return the index of an element equal to a given value or matching some predicate. * **Addition operations** `prepended`, `prependedAll`, `appended`, `appendedAll`, `padTo`, which return new sequences obtained by adding elements at the front or the end of a sequence. * **Update operations** `updated`, `patch`, which return a new sequence obtained by replacing some elements of the original sequence. diff --git a/_overviews/collections-2.13/trait-iterable.md b/_overviews/collections-2.13/trait-iterable.md index 4e67903189..66a8bdcb41 100644 --- a/_overviews/collections-2.13/trait-iterable.md +++ b/_overviews/collections-2.13/trait-iterable.md @@ -14,7 +14,13 @@ permalink: /overviews/collections-2.13/:title.html At the top of the collection hierarchy is trait `Iterable`. All methods in this trait are defined in terms of an abstract method, `iterator`, which yields the collection's elements one by one. - def iterator: Iterator[A] +{% tabs trait-iterable_1 %} +{% tab 'Scala 2 and 3' for=trait-iterable_1 %} +```scala +def iterator: Iterator[A] +``` +{% endtab %} +{% endtabs %} Collection classes that implement `Iterable` just need to define this method; all other methods can be inherited from `Iterable`. @@ -31,27 +37,33 @@ Collection classes that implement `Iterable` just need to define this method; al * **Element tests** `exists`, `forall`, `count` which test collection elements with a given predicate. * **Folds** `foldLeft`, `foldRight`, `reduceLeft`, `reduceRight` which apply a binary operation to successive elements. * **Specific folds** `sum`, `product`, `min`, `max`, which work on collections of specific types (numeric or comparable). -* **String** operations `mkString`, `addString`, `className`, which give alternative ways of converting a collection to a string. +* **String** operations `mkString`, `addString`, and the protected `className`, which give alternative ways of converting a collection to a string. * **View** operation: A view is a collection that's evaluated lazily. You'll learn more about views in [later]({% link _overviews/collections-2.13/views.md %}). Two more methods exist in `Iterable` that return iterators: `grouped` and `sliding`. These iterators, however, do not return single elements but whole subsequences of elements of the original collection. The maximal size of these subsequences is given as an argument to these methods. The `grouped` method returns its elements in "chunked" increments, where `sliding` yields a sliding "window" over the elements. The difference between the two should become clear by looking at the following REPL interaction: - scala> val xs = List(1, 2, 3, 4, 5) - xs: List[Int] = List(1, 2, 3, 4, 5) - scala> val git = xs grouped 3 - git: Iterator[List[Int]] = non-empty iterator - scala> git.next() - res3: List[Int] = List(1, 2, 3) - scala> git.next() - res4: List[Int] = List(4, 5) - scala> val sit = xs sliding 3 - sit: Iterator[List[Int]] = non-empty iterator - scala> sit.next() - res5: List[Int] = List(1, 2, 3) - scala> sit.next() - res6: List[Int] = List(2, 3, 4) - scala> sit.next() - res7: List[Int] = List(3, 4, 5) +{% tabs trait-iterable_2 %} +{% tab 'Scala 2 and 3' for=trait-iterable_2 %} +``` +scala> val xs = List(1, 2, 3, 4, 5) +xs: List[Int] = List(1, 2, 3, 4, 5) +scala> val git = xs grouped 3 +git: Iterator[List[Int]] = non-empty iterator +scala> git.next() +res3: List[Int] = List(1, 2, 3) +scala> git.next() +res4: List[Int] = List(4, 5) +scala> val sit = xs sliding 3 +sit: Iterator[List[Int]] = non-empty iterator +scala> sit.next() +res5: List[Int] = List(1, 2, 3) +scala> sit.next() +res6: List[Int] = List(2, 3, 4) +scala> sit.next() +res7: List[Int] = List(3, 4, 5) +``` +{% endtab %} +{% endtabs %} ### Operations in Class Iterable ###