天天看點

[scala基礎]--定義容器

從頭定義新容器

我們已經知道​

​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為元素的Vector​​​​Iterator(1, 2, 3) // 一個疊代器,可傳回三個整數​​​​Set(dog, cat, bird) // 一個包含三個動物的集合​​​​HashSet(dog, cat, bird) // 一個包含三個同樣動物的HashSet​​​​Map('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))、……