diff --git a/_zh-cn/overviews/scala3-book/collections-classes.md b/_zh-cn/overviews/scala3-book/collections-classes.md index 307395fba9..c102860b53 100644 --- a/_zh-cn/overviews/scala3-book/collections-classes.md +++ b/_zh-cn/overviews/scala3-book/collections-classes.md @@ -119,6 +119,8 @@ NOTE: those images come from this page: https://docs.scala-lang.org/overviews/co 这是创建初始“列表”的方式: +{% tabs list-creation %} +{% tab 'Scala 2 and 3' %} ```scala val ints = List(1, 2, 3) val names = List("Joel", "Chris", "Ed") @@ -126,19 +128,36 @@ val names = List("Joel", "Chris", "Ed") // another way to construct a List val namesAgain = "Joel" :: "Chris" :: "Ed" :: Nil ``` +{% endtab %} +{% endtabs %} 如果您愿意,也可以声明 `List` 的类型,但通常不是必需的: +{% tabs list-type %} +{% tab 'Scala 2 and 3' %} ```scala val ints: List[Int] = List(1, 2, 3) val names: List[String] = List("Joel", "Chris", "Ed") ``` +{% endtab %} +{% endtabs %} 一个例外是集合中有混合类型时。在这种情况下,您可能需要明确指定其类型: +{% tabs list-mixed-types class=tabs-scala-version %} +{% tab 'Scala 2' %} ```scala val things: List[Any] = List(1, "two", 3.0) ``` +{% endtab %} + +{% tab 'Scala 3' %} +```scala +val things: List[String | Int | Double] = List(1, "two", 3.0) // with union types +val thingsAny: List[Any] = List(1, "two", 3.0) // with any +``` +{% endtab %} +{% endtabs %} ### 将元素添加到列表 @@ -146,16 +165,24 @@ val things: List[Any] = List(1, "two", 3.0) 相反,您可以通过将元素添加到现有 `List` 来创建新列表。 例如,给定这个 `List`: +{% tabs adding-elements-init %} +{% tab 'Scala 2 and 3' %} ```scala val a = List(1, 2, 3) ``` +{% endtab %} +{% endtabs %} 使用 `List` 时,用 `::` 来_附加_一个元素,用 `:::` 把另一个 `List` 插在这个 `List` 之前,如下所示: +{% tabs adding-elements-example %} +{% tab 'Scala 2 and 3' %} ```scala val b = 0 :: a // List(0, 1, 2, 3) val c = List(-1, 0) ::: a // List(-1, 0, 1, 2, 3) ``` +{% endtab %} +{% endtabs %} 你也可以在 `List` 中添加元素,但是因为 `List` 是一个单链表,你通常应该只在它前面添加元素; 在它的后面添加元素是一个相对较慢的操作,尤其是在处理大型序列时。 @@ -170,15 +197,23 @@ val c = List(-1, 0) ::: a // List(-1, 0, 1, 2, 3) 现在 IDE 为我们提供了极大的帮助,但是记住这些方法名称的一种方法是,认为 `:` 字符代表序列所在的一侧,因此当您使用 `+:` 时,您知道列表需要在右边,像这样: +{% tabs list-prepending %} +{% tab 'Scala 2 and 3' %} ```scala 0 +: a ``` +{% endtab %} +{% endtabs %} 同样,当您使用 `:+` 时,您知道列表需要在左侧: +{% tabs list-appending %} +{% tab 'Scala 2 and 3' %} ```scala a :+ 4 ``` +{% endtab %} +{% endtabs %} 有更多的技术方法可以考虑这一点,但这可能是记住方法名称的有用方法。 @@ -194,24 +229,51 @@ LATER: Add a discussion of `:` on method names, right-associativity, and infix o 给定一个名称 `List`: +{% tabs list-loop-init %} +{% tab 'Scala 2 and 3' %} ```scala val names = List("Joel", "Chris", "Ed") ``` +{% endtab %} +{% endtabs %} 您可以像这样打印每个字符串: +{% tabs list-loop-example class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +for (name <- names) println(name) +``` +{% endtab %} + +{% tab 'Scala 3' %} ```scala for name <- names do println(name) ``` +{% endtab %} +{% endtabs %} 这是它在 REPL 中的样子: +{% tabs list-loop-repl class=tabs-scala-version %} +{% tab 'Scala 2' %} +```scala +scala> for (name <- names) println(name) +Joel +Chris +Ed +``` +{% endtab %} + +{% tab 'Scala 3' %} ```scala scala> for name <-names do println(name) Joel Chris Ed ``` +{% endtab %} +{% endtabs %} 将 `for` 循环与集合一起使用的一个好处是 Scala 是一致的,并且相同的方法适用于所有序列,包括 `Array`、`ArrayBuffer`、`List`、`Seq`、`Vector`、`Map` ,`Set` 等。 @@ -220,22 +282,34 @@ Ed 对于那些对历史感兴趣的人,Scala `List` 类似于 [Lisp 编程语言](https://en.wikipedia.org/wiki/Lisp_(programming_language)) 中的 `List`,它是最初于 1958 年确定的。 实际上,除了像这样创建一个 `List` 之外: +{% tabs list-history-init %} +{% tab 'Scala 2 and 3' %} ```scala val ints = List(1, 2, 3) ``` +{% endtab %} +{% endtabs %} 您也可以通过这种方式创建完全相同的列表: +{% tabs list-history-init2 %} +{% tab 'Scala 2 and 3' %} ```scala val list = 1 :: 2 :: 3 :: Nil ``` +{% endtab %} +{% endtabs %} REPL 展示了它是如何工作的: +{% tabs list-history-repl %} +{% tab 'Scala 2 and 3' %} ```scala scala> val list = 1 :: 2 :: 3 :: Nil list: List[Int] = List(1, 2, 3) ``` +{% endtab %} +{% endtabs %} 这是因为 `List` 是一个以 `Nil` 元素结尾的单链表,而 `::` 是一个 `List` 方法,其工作方式类似于 Lisp 的“cons”运算符。 @@ -246,22 +320,30 @@ Scala 集合还包括一个 [LazyList](https://www.scala-lang.org/api/current/sc 你可以看到 REPL 中的 `LazyList` 有多懒惰: +{% tabs lazylist-example %} +{% tab 'Scala 2 and 3' %} ```scala val x = LazyList.range(1, Int.MaxValue) x.take(1) // LazyList() x.take(5) // LazyList() x.map(_ + 1) // LazyList() ``` +{% endtab %} +{% endtabs %} 在所有这些例子中,什么都没有发生。 事实上,除非你强迫它发生,否则什么都不会发生,例如通过调用它的 `foreach` 方法: -```` +{% tabs lazylist-evaluation-example %} +{% tab 'Scala 2 and 3' %} +```scala scala> x.take(1).foreach(println) 1 -```` +``` +{% endtab %} +{% endtabs %} -有关严格和非严格的用途、好处和缺点的更多信息严格(惰性)集合,请参阅 [The Architecture of Scala 2.13's Collections][strict] 页面上的“严格”和“非严格”讨论。 +有关严格和非严格的用途、好处和缺点的更多信息严格(惰性)集合,请参阅 [Scala 2.13集合的架构][strict] 页面上的“严格”和“非严格”讨论。