從頭定義新容器
我們已經知道
List(1, 2, 3)
可以建立出含有三個元素的清單,用
Map('A' -> 1, 'C' -> 2)
可以建立含有兩對綁定的映射。實際上各種Scala容器都支援這一功能。任意容器的名字後面都可以加上一對帶參數清單的括号,進而生成一個以這些參數為元素的新容器。不妨再看一些例子:
Traversable() // 一個空的Traversable對象List() // 空清單List(1.0, 2.0) // 一個以1.0、2.0為元素的清單Vector(1.0, 2.0) // 一個以1.0、2.0為元素的VectorIterator(1, 2, 3) // 一個疊代器,可傳回三個整數Set(dog, cat, bird) // 一個包含三個動物的集合HashSet(dog, cat, bird) // 一個包含三個同樣動物的HashSetMap('a' -> 7, 'b' -> 0) // 一個将字元映射到整數的Map
實際上,上述每個例子都被“暗地裡”轉換成了對某個對象的apply方法的調用。例如,上述第三行會展開成如下形式:
List.apply(1.0, 2.0)
可見,這裡調用的是List類的伴生對象的apply方法。該方法可以接受任意多個參數,并将這些參數作為元素,生成一個新的清單。在Scala标準庫中,無論是List、Stream、Vector等具體的實作類還是Seq、Set、Traversable等抽象基類,每個容器類都伴一個帶apply方法的伴生對象。針對後者,調用apply方法将得到對應抽象基類的某個預設實作,例如:
scala > List(1,2,3)res17: List[Int] = List(1, 2, 3)scala> Traversable(1, 2, 3)res18: Traversable[Int] = List(1, 2, 3)scala> mutable.Traversable(1, 2, 3)res19: scala.collection.mutable.Traversable[Int] = ArrayBuffer(1, 2, 3)
除了apply方法,每個容器類的伴生對象還定義了一個名為empty的成員方法,該方法傳回一個空容器。也就是說,
List.empty
可以代替
List()
,
Map.empty
可以代替
Map()
,等等。
Seq的子類同樣在它們伴生對象中提供了工廠方法,總結如下表。簡而言之,有這麼一些:
concat,将任意多個Traversable容器串聯起來
fill 和 tabulate,用于生成一維或者多元序列,并用給定的初值或打表函數來初始化。
range,用于生成步長為step的整型序列,并且iterate,将某個函數反複應用于某個初始元素,進而産生一個序列。
序列的工廠方法
WHAT IT IS | WHAT IT DOES |
S.empty | 空序列 |
S(x, y, z) | 一個包含x、y、z的序列 |
S.concat(xs, ys, zs) | 将xs、ys、zs串街起來形成一個新序列。 |
S.fill(n) {e} | 以表達式e的結果為初值生成一個長度為n的序列。 |
S.fill(m, n){e} | 以表達式e的結果為初值生成一個次元為m x n的序列(還有更高次元的版本) |
S.tabulate(n) {f} | 生成一個廠素為n、第i個元素為f(i)的序列。 |
S.tabulate(m, n){f} | 生成一個次元為m x n,第(i, j)個元素為f(i, j)的序列(還有更高次元的版本)。 |
S.range(start, end) | start, start + 1, … end-1的序列。(譯注:注意始左閉右開區間) |
S.range(start, end, step) | 生成以start為起始元素、step為步長、最大值不超過end的遞增序列(左閉右開)。 |
S.iterate(x, n)(f) | 生成一個長度為n的序列,其元素值分别為x、f(x)、f(f(x))、…… |