日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Scala 集合入门

發(fā)布時(shí)間:2023/11/27 生活经验 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scala 集合入门 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 數(shù)組

1.1 定長數(shù)組

scala.Array 是定長的可變的索引型集合, JVM 中, Scala 的 Array 是以 Java 數(shù)組方式實(shí)現(xiàn). String 對(duì)應(yīng) java.lang.String, Int, Double或其他與 Java 中基本類型對(duì)應(yīng)數(shù)組都有基本類型數(shù)組, 比如說 Array(1, 2) 在 JVM 中就是一個(gè) int[].

val arr1 = new Array[Int](10)
val arr2 = Array(1, 3)  // 調(diào)用apply方法
arr2(1)  // 3,  apply 方法
arr2(1) = 2  // 可以改變 Array 中的值 ,  update 方法

1.2 變長數(shù)組

scala.collection.mutable.ArrayBuffer 是變長的可變的索引型集合, 在 ArrayBuffer 的尾部添加和刪除元素是一個(gè)高效的操作, 你也可以在任何位置插入或者移除元素, 但是這樣的操作并不那么高效

import  scala.collection.mutable.ArrayBufferval b = ArrayBuffer[Int]()  // 或 val b = ArrayBuffer[Int]
b += 1  // += 在尾部添加元素  1
b += (2 ,3)  // += 尾部添加多個(gè)元素,  用括號(hào)括起來 1, 2, 3
b ++= Array(4, 5)  // ++= 用來追加任何集合 1 2 3 4 5b.trimEnd(2)  //  刪除尾部2個(gè)元素; 1 2 3
b.trimStart(1)  // 刪除頭部2個(gè)元素 2 3b.insert(1, 4)  // 在下標(biāo)1之前插入4;  2 4 3
b.insert(1, 6, 7)  // 在下標(biāo)1之前插入6, 7;  2 6 7 4 3b.remove(2)  // 刪除 b(2);  2 6 4 3
b.remove(2, 2)  // 刪除 b.slice(2, 2+2);  2 6

如果你需要一個(gè) Array, 但是不知道最終要裝多少個(gè)元素, 你可以向使用 ArrayBuffer, 然后調(diào)用 b.toArray; 反過來你也可以使用 toBuffer 將數(shù)組轉(zhuǎn)換為 ArrayBuffer

\(\color {red} {變長數(shù)組在 for 循環(huán)中有刪除操作引發(fā)的不良后果}\)

scala> val ab = ArrayBuffer(1,2,3,4)
ab: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
scala> for (i<-0  until ab.size){if (ab(i) <3) ab.remove(i);println(ab)}
ArrayBuffer(2, 3, 4)
ArrayBuffer(2, 3, 4)
ArrayBuffer(2, 3, 4)
error: java.lang.IndexOutOfBoundsException: 3

1.3 遍歷數(shù)組與數(shù)組轉(zhuǎn)化

遍歷數(shù)組

for ( i <- 0 until a.length)
for (i <- (0 until a.length).reverse)  
for (elem <- a)

數(shù)組轉(zhuǎn)換
利用 for (...) yield 循環(huán)會(huì)創(chuàng)建 一個(gè)類型和原始集合相同的集合的特點(diǎn)

val res = for(elem <- a if elem % 2 == 1)  yield 2 * elem   

上面的寫法等價(jià)于

val res = a.filter(_ % 2 == 1).map(2 *_)

這里只是展示下 for 推導(dǎo)式在集合上的應(yīng)用, 實(shí)際上, 在 Scala 中很少使用這種顯示的循環(huán)結(jié)構(gòu), 更多的是利用函數(shù)來解決問題, 比如上面用到的 map 和 filter

1. 4 常用方法

val a = Array(1, 4, 3)  // 或 val a = ArrayBuffer(1, 4, 3)
a.sum  // 8
a.max  // 4
a.sortWith(_<_) // 1 3 4,  返回一個(gè)新集合,  a 并沒有改變
scala.util.Sorting.quickSort(a)

下面看一下 toString 和 mkString方法

mkString 方法允許你指定元素之間的分隔符, 該方法的兩個(gè)重載版本還可以指定前綴和后綴

val a = Array(2, 3)  
val b = ArrayBuffer(2, 3)  scala> a.toString
res52: String = [I@52fa6742
scala> b.toString
res53: String = ArrayBuffer(2, 3)scala> a.mkString
res60: String = 23
scala> a.mkString(" and ")
res61: String = 2 and 3
scala> a.mkString("(",  ",", ")")
res62: String = (2,3)

從上面可以看出來, 如果是 Array 的話, 可以使用 mkString 方法將 Array 的內(nèi)容打印到控制臺(tái)

1. 5 多維數(shù)組

在 Scala中, 多維數(shù)組通過數(shù)組數(shù)組來實(shí)現(xiàn). 比如說 Double 的二維數(shù)組類型為 Array[Array[Double]]

要構(gòu)造這樣的數(shù)組可以使用 ofDim 方法:

val ndim = Array.ofDim[Double](3, 4)

訪問其中元素:
ndim(row)(column)

也可以自己創(chuàng)建一個(gè)不規(guī)則的數(shù)組

val triangle = new Array[Array[Int]](4)  // 4 是二維數(shù)組的行數(shù)
for (i <- 0 until triangle.length) {triangle(i) = new Array[Int](i + 1)
}

2. 元組

元組是不同類型的值的組合, 這些不同類型值包裹在在括號(hào) ( ) 中; 和數(shù)組和字符串的不同, 元組的組元從1開始, 而不是 0, 你可以使用 _1, _2, ... 訪問其組元; 可以通過模式匹配快速提取元組中的值.

 scala> val t = (1, 1.414,  "jerry")t: (Int, Double, String) = (1,1.414,jerry)scala>  t._1res18: Int = 1scala>  val (first, second, third) = tfirst: Int = 1second: Double = 1.414third: String = jerryscala> val (first, _, _) = t  // 如果只是需要使用第一個(gè)組元, 可以在不需要的位置使用 _first: Int = 1

3. 映射

有句經(jīng)典的程序員名言, "如果只能有一種數(shù)據(jù)結(jié)構(gòu)就用映射吧"

3.1 構(gòu)造映射

Scala中, 映射是對(duì)偶的集合. 簡單的說, 對(duì)偶就是2個(gè)值的元組, -> 操作符可以創(chuàng)建對(duì)偶, Scala會(huì)將 A->B 隱式轉(zhuǎn)換為2元組 (A,B). 使用 -> 操作符只是因?yàn)?-> 更加符合人們對(duì)映射的直觀感.

Scala 默認(rèn)選擇不可變映射, scala.collecton.immutable.Map, 如果你想要一個(gè)可變映射, 使用 scala.collecton.mutable.Map; 如果你想從一個(gè)空映射開始, 你需要指定映射的實(shí)現(xiàn)以及類型參數(shù)(可變與不可變都不可以直接 new Map[k, v]).

scala> val iage = Map("tom"->3, "jerry"->4)  
iage: scala.collection.immutable.Map[String,Int] = Map(tom -> 3, jerry -> 4)scala> val age =  scala.collection.mutable.Map(("tom",3), ("jerry"->4))
age: scala.collection.mutable.Map[String,Int] = Map(tom -> 3, jerry -> 4)scala> val m1 = new Map[Int, Int]
<console>:15: error: trait Map is abstract; cannot be instantiatedscala> val m2 = new scala.collection.mutable.HashMap[Int, Int]
m2: scala.collection.mutable.HashMap[Int,Int] = Map()

已排序映射

在操作映射時(shí), 你需要指定一個(gè)實(shí)現(xiàn), 哈希表或者一個(gè)平衡樹, 默認(rèn)是哈希映射. 如果你不僅有查找需求還有排序需求的話, 可以使用樹形映射; Scala 2.12 中不可變樹形映射和可變樹形映射都有.

scala> val age = scala.collection.mutable.SortedMap("tom"->3, "jerry"->4)
age: scala.collection.mutable.SortedMap[String,Int] = TreeMap(jerry -> 4, tom -> 3)scala> val  iage = scala.collection.immutable.SortedMap("tom"->3, "jerry"->4)
iage: scala.collection.immutable.SortedMap[String,Int] = Map(jerry -> 4, tom -> 3)

3.2 獲取映射中的值

獲取映射值: 映射通過 () 表示法調(diào)用 apply 方法來查找某個(gè)鍵對(duì)應(yīng)的值; 如果映射中不包含請(qǐng)求中使用的鍵, 會(huì)拋出異常, 可以通過 contains 方法檢查映射是否包含某個(gè)鍵; 也可以使用 getOrElse 方法和 get 方法, get 方法返回一個(gè) Option對(duì)象.

val tom = age("tom")  // 3
val kitty = age.getOrElse("kitty", -1)  // -1, 獲取鍵對(duì)應(yīng)值,  若鍵不存在,  返回傳入值
val jerry = age.get("jerry")  // jerry

3.3 更新映射

在可變映射中, 你可以更新某個(gè)映射的值, 或者添加一個(gè)新的對(duì)偶, 方法是 映射(key) = value , 這會(huì)調(diào)用 update 方法; 如果 key 在映射中則更新, 不在映射中則添加;

對(duì)于不可變映射, 雖然你不能改變一個(gè)不可變映射, 不過你可以通過不可變映射創(chuàng)建一個(gè)新映射, 更新和添加對(duì)偶, 新映射也是不可變集合, 因?yàn)樾掠成浜屠系挠成涔蚕泶蟛糠纸Y(jié)構(gòu), 這樣創(chuàng)建新映射的效率會(huì)很高.

// 可變映射
age("tom") = 4   // age.update("tom",  4)
//  更新, 輸出 scala.collection.mutable.Map[String,Int] = Map(tom -> 4, jerry -> 4)age("kitty") = 5
// 添加, 輸出 scala.collection.mutable.Map[String,Int] = Map(tom -> 4, kitty -> 5, jerry -> 4)// 不可變映射// 更新,  新映射也是不變的
var newAge = iage + ("tom"->64)
// 輸出 scala.collection.immutable.Map[String,Int] = Map(tom -> 64, jerry -> 4)// 添加, 輸出也可以看出來 iage 并沒有改變,  tom ->3,  
var newAge: scala.collection.mutable.Map[String,Int]  = iage + ("kitty"->6)
// 輸出newAge: scala.collection.immutable.Map[String,Int] = Map(tom -> 3, jerry -> 4, kitty -> 6)

對(duì)于可變映射, 可以通過 += 操作符添加多個(gè)對(duì)偶, 要移除某個(gè)對(duì)偶使用 -=;

age += ("snow" -> 1, "dneyis"->3)
age -= "tom"  // 即使映射中沒有 tom, 也不會(huì)報(bào)錯(cuò)

3.4 遍歷映射

for ((k, v) <- 映射) yield (k, v)
for ((k, v) <- 映射) yield (v, k)  // 交換鍵和值的位置

這里通過模式匹配迭代獲取映射中的對(duì)偶, 從而遍歷了映射; Scala 中提供了方法來訪問鍵和值

scala> age.keyS
keySet   keys   keysIteratorscala> age.values
values   valuesIterator

3.5 拉鏈操作

使用元組原因之一就是把多個(gè)值綁在一起, 以便它們能一起處理, 這通常用 zip 方法來完成. 比如說

val name = Array("tom", "jerry")
val age = Array(3 , 4)
val pairs = name.zip(age)  // pairs: Array[(String, Int)] = Array((tom,3), (jerry,4))

如果你有一個(gè)鍵的集合, 以及一個(gè)與之平行對(duì)應(yīng)的值的集合, 那么你就可以用拉鏈操作將它們組合成一個(gè)映射了, 然后通過 Array 的 toMap 方法對(duì)偶的集合轉(zhuǎn)換成映射, 最后結(jié)合 for ((k, v) <- 映射) yield statements, 這些對(duì)偶就可以被一起處理了

keys.zip(values).toMap
for ((k, v) <- 映射) yield statements

4. 排序

全部排序

下面引用 Scala 使用指南的例子說說集合該如何排序.

特質(zhì) Ordering 及其 on方法定義如下

trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializableon[U](f: (U) ? T): Ordering[U]
Given f, a function from U into T, creates an Ordering[U] whose compare function is equivalent to:
def compare(x:U, y:U) = Ordering[T].compare(f(x), f(y))

Ordering 特質(zhì)的伴生對(duì)象 Ordering 及其 by 方法定義如下

object Ordering extends LowPriorityOrderingImplicits with Serializabledef by[T, S](f: (T) ? S)(implicit ord: Ordering[S]): Ordering[T]
Given f, a function from T into S, creates an Ordering[T] whose compare function is equivalent to:
def compare(x:T, y:T) = Ordering[S].compare(f(x), f(y))
This function is an analogue(類似物) to Ordering.on where the Ordering[S] parameter is passed implicitly.

on[U](f: (U) ? T)
首先特質(zhì)定義中 Ordering[T] 的 T 表明該特質(zhì)用于 T 類型數(shù)據(jù)的排序. on 方法定義表明輸入為 U 數(shù)據(jù)類型, 而 Ordering[T] 只能對(duì) T 類型數(shù)據(jù)進(jìn)行排序, 所以 on 方法接收 f: (U) ? T 的函數(shù), 然后對(duì)函數(shù)輸出的 T 數(shù)據(jù)類型進(jìn)行排序.

by[T, S](f: (T) ? S)(implicit ord: Ordering[S])
Ordering 對(duì)象的 by 方法定義表明輸入為 T 數(shù)據(jù)類型, 但是卻要對(duì) S 型數(shù)據(jù)排序, 所以需要能對(duì) S 型數(shù)據(jù)排序的 Ordering[S], 故需要傳入能對(duì) S 型數(shù)據(jù)進(jìn)行排序的Ordering[S]. 所以 by 方法接收 f: (T) ? S 的函數(shù), 然后對(duì)函數(shù)輸出的 S 數(shù)據(jù)類型進(jìn)行排序.

由于 Scala 具有自動(dòng)類型推斷的能力, 所以有時(shí)我們可以省略類型.下面看看例子吧

例子

import scala.util.Sorting
val pairs = Array(("a", 5, 2), ("c", 3, 1), ("b", 1, 3))// sort by 2nd element, [(String, Int, Int), Int] 是函數(shù)類型
// Ordering 為對(duì)象
Sorting.quickSort(pairs)(Ordering.by[(String, Int, Int), Int](_._2))// sort by the 3rd element, then 1st
// Ordering[(Int, String)]為特質(zhì), 不省略類型即為 
// Sorting.quickSort(pairs)(Ordering[(Int, String)].on[(String, Int, Int)](x => (x._3, x._1)))
Sorting.quickSort(pairs)(Ordering[(Int, String)].on(x => (x._3, x._1)))

最大值

// 默認(rèn)按照第一個(gè)排序
def max: A// 可以選擇排序的元素
def maxBy[B](f: (A) ? B): A

舉個(gè)例子

scala> val arr = Array(("a", 5, 2), ("c", 2, 3), ("b", 3, 3))
scala> arr.max
res43: (String, Int, Int) = (c,2,3)scala> arr.maxBy(_._2)
res44: (String, Int, Int) = (a,5,2)scala> arr.maxBy(_._3)
res45: (String, Int, Int) = (c,2,3)scala> arr.maxBy(x=>(x._3,x._2))
res47: (String, Int, Int) = (b,3,3)

轉(zhuǎn)載于:https://www.cnblogs.com/nowgood/p/Scala%e9%9b%86%e5%90%88%e5%85%a5%e9%97%a8.html

總結(jié)

以上是生活随笔為你收集整理的Scala 集合入门的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。