1. 程式人生 > >Scala 學習筆記(三) Scala的陣列、對映、元組、集合、關鍵字Lazy

Scala 學習筆記(三) Scala的陣列、對映、元組、集合、關鍵字Lazy

文章目錄

一、陣列

1、定長陣列和可變陣列

在Scala中,Array是定長陣列型別,而ArrayBuffer型別是可變陣列型別

   import scala.collection.mutable.ArrayBuffer

object ArrayTest2{

  def main(args: Array[String]): Unit = {
    // 初始化一個長度為8的定長陣列,器所有元素均為0
    val arr1 = new Array[Int](8)
    // 直接列印定長陣列,內容為陣列的hashcode值
    println("arr1"+arr1)

    // 將陣列轉換成陣列緩衝,就可以看到源陣列中的內容了
    // toBuffer會將陣列轉換成長陣列緩衝  初始化的int型別為 0
    println("arr1.toBuffer"+arr1.toBuffer)
    // toString  列印了 hashcode值
    println("arr1.toString"+arr1.toString)

    // 定義一個長度為3的定長陣列
    val arr2 = Array("Hadoop","Storm","Spark")
    // 使用 () 來訪問元素  陣列的索引也是從 0 開始
    print("arr3(2)="+arr2(2))

    //////////////////////////////////////////////////////
println("-----------------------------------------------------------")
    // 可變陣列 (ArrayBuffer) 陣列緩衝
    // 使用可變陣列需要匯入 scala.collection.mutable.ArrayBuffer包
    var ad =  ArrayBuffer[Int]()
    // 向陣列緩衝的尾部追加一個元素 +=
    ad += 1
    // 追加多個元素,用元組型別包裹  +=
    ad += (2,3,4,5)
    println("ad1="+ad)
    // 追加一個不變陣列或可變陣列  ++=
    ad ++= Array(6,7)
    ad ++= ArrayBuffer(8,9,10)
    println("ad2="+ad)

    // 在陣列的某個位置插入元素 用insert(插入位置索引,插入數值1,插入數值2,....)
    //ad.insert(0,-3,-2,-1)
    println("ad3"+ad)

    // 刪除陣列某個位置的元素用remove(刪除位置的索引,從該位置的刪除數量)
    ad.remove(7,2)
    println("ab4="+ad)
    
  }
}

2、遍歷陣列

(1) 增強for迴圈
(2) until 關鍵字,生成Range型別: 0 until 100

scala> 0 until 10(包含0,但不包括10)
res1: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

遍歷陣列相關程式碼如下:

object ArrayTraverse{

  def main(args: Array[String]): Unit = {
    // 初始化 一個數組
    val arr = Array[Int](2,3,4,5,6,7,8,9,10)
    // 1、增強for迴圈 <-  迭代法
    for(i <- arr)
      print(i+"\t")
    println()

    // 2、使用until關鍵字 ,利用下標索引
    for(i <- (0 until arr.length))
      print(arr(i)+"\t")
    println()
    // 3、 反轉遍歷   利用 range的 reverse 屬性
    println("反轉變數")
    for(i <- (0 until arr.length).reverse)
      print(arr(i)+"\t")
  }

}

3、陣列轉換

yield 關鍵字將原始的陣列進行轉換會產生一個性的陣列,原始的陣列不變
陣列型別的物件的map方法可以作用於陣列的每個元素

scala> val arr = Array(1,2,3,4,5,6,7,8)
arr: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

scala> val res = for(e <-arr) yield e*2
res: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16)

scala> res
res5: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16)

scala> arr.map(_*2)
res6: Array[Int] = Array(2, 4, 6, 8, 10, 12, 14, 16)

遍歷如下:

object ArrayTransfer{
  def main(args: Array[String]): Unit = {
   //定義一個數組
  val arr = Array(1,2,3,4,5,6,7,8,9,10)
   // 將arr的反序取數並分別乘10
    println("arr: "+arr.toBuffer)
  val arr2 = for(i <- (0 until arr.length).reverse) yield i*10
  println("arr2: "+arr2)
    // 將偶數取出,再乘以10
    val arr3 = for (e <- arr if e % 2 ==0) yield e * 10
    println("arr3: "+arr3.toBuffer)

  // 更高階的寫法
    // 陣列物件的filter屬性是過濾,接收一個返回值為boolean的函式
    // map相當於map中的方法作用於陣列中每一個元素
    val arr4 = arr.filter(_ % 2 == 0).map(_ * 10)
    println("arr4: "+arr4.toBuffer)
}
}

4、常用陣列的屬性

陣列物件有 sum\max\min\sorted等屬性

scala> val arr= Array(2,5,1,4,3)
arr: Array[Int] = Array(2, 5, 1, 4, 3)

scala> arr.sum
res8: Int = 15

scala> arr.max
res9: Int = 5

scala> arr.min
res10: Int = 1

scala> arr.sorted
res12: Array[Int] = Array(1, 2, 3, 4, 5)

二、對映(Map)

在Scala中,把雜湊表這種資料結構稱為對映Map,對映的組成:key,value,其中key是唯一的。

1、構建對映的方式

建立Map的方式一:->(箭頭)
scala> val scores = Map("wangbaooqiang" -> 66,"huangbo" ->77,"yemin"->93)
scores: scala.collection.immutable.Map[String,Int] = Map(wangbaooqiang -> 66, huangbo -> 77, yemin -> 93)

scala> scores
res13: scala.collection.immutable.Map[String,Int] = Map(wangbaooqiang -> 66, huangbo -> 77, yemin -> 93)
建立Map的方式二:元組
scala> val scores2= Map(("yemin",66),("xuzheng",77),("huangbo",88))
scores2: scala.collection.immutable.Map[String,Int] = Map(yemin -> 66, xuzheng -> 77, huangbo -> 88)

scala> scores2
res14: scala.collection.immutable.Map[String,Int] = Map(yemin -> 66, xuzheng -> 77, huangbo -> 88)

2、獲取對映的值

scala> scores2
res14: scala.collection.immutable.Map[String,Int] = Map(yemin -> 66, xuzheng -> 77, huangbo -> 88)
獲取map的value值 方法一 : ()
scala> scores2("yemin")
res16: Int = 66
獲取map的value值 方法二 : get()
scala> scores2.get("yemin")
res17: Option[Int] = Some(66)
獲取map的value值 方法二 : getOrElse()有就返回對應的值,沒有就返回預設值
scala> scores2.getOrElse("yem",0)
res18: Int = 0
scala> scores2.getOrElse("yemmin",0)
res19: Int = 0

另外主要注意的是:
在Scala中有兩種Map:
不可變的Map:在immutable包下的Map
可變的Map: 在mutable包下的Map

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

scala> val scores = Map("tom"->80,"greeye"-> 95)
scores: scala.collection.mutable.Map[String,Int] = Map(greeye -> 95, tom -> 80)
 # 修改Map greeye對應的值為100
scala> scores("greeye") = 100
 
scala> scores
res21: scala.collection.mutable.Map[String,Int] = Map(greeye -> 100, tom -> 80)
# 追加鍵值對到Map中 +=
scala> scores +=("xiaoming"->101)
res25: scores.type = Map(greeye -> 100, tom -> 80, xiaoming -> 101)

總結:
1、是否可以修改值
Mutable包匯入的map 可以修改map的值
Immutable包匯入的map 不能修改裡面的值
2、是否可以追加元素
mutable var/val 都可以追加元素(+=)
immutable var型別map可以追加,val型別資料不能追加元素

三、元組

元組(tuple)是一個對映的特點:
1、元組是不可變的
2、元組的元素可以包含各種不同的型別元素,這個相對於array、map和set是很大的不同,
3、對偶元組可以轉化成map對映型別
4、可以通過陣列物件型別的zip方法將兩個array型別繫結成對偶元組

1、建立元組

定義元組是用小括號將多個元素包在起來,元素之間用逗號分隔,元素的型別可以不一樣,元素個數可以任意多個

scala> val t = ("hadoop",3.14,65535)
t: (String, Double, Int) = (hadoop,3.14,65535)

2、獲取元組中的值

有兩種獲取方式:
第一種方法是 等式分解,這種方式需要左邊比元組內元素的個數多一個數,適合小數量元組
第二種方法是 下標獲取_1,_2 可以通過固定的下標,獲取對應位置的的元組元素

scala> val t = ("hadoop",3.14,65535)
t: (String, Double, Int) = (hadoop,3.14,65535)
# 第一種方式獲取元組的元素值
scala> val tt,(a,b,c) = t
tt: (String, Double, Int) = (hadoop,3.14,65535)
a: String = hadoop
b: Double = 3.14
c: Int = 65535

scala> a
res28: String = hadoop

scala> b
res29: Double = 3.14

scala> c
res30: Int = 65535
# 第二種方式獲取元組的元素值,下標獲取 _1 _2 _3
scala> val t1 = t._1
t1: String = hadoop

scala> t1
res35: String = hadoop

3、將對偶元組轉換成對映

# 將多個對偶元組整合成array陣列
scala> var arr = Array(("tom",88),("jerry",95))
arr: Array[(String, Int)] = Array((tom,88), (jerry,95))
# toMap可以將對偶的集合轉換成對映
scala> val m = arr.toMap
m: scala.collection.immutable.Map[String,Int] = Map(tom -> 88, jerry -> 95)

4、zip拉鍊操作

scala> var va = Array(77,66,99)
va: Array[Int] = Array(77, 66, 99)

scala> var ke = Array("ye","min","Greeye")
ke: Array[String] = Array(ye, min, Greeye)
# zip的是將物件中對應的元素打包成一個個元組,然後返回由這些元組組成的array陣列
scala> ke.zip(va)
res52: Array[(String, Int)] = Array((ye,77), (min,66), (Greeye,99))

scala> val keva = ke.zip(va)
keva: Array[(String, Int)] = Array((ye,77), (min,66), (Greeye,99))

scala> keva.toMap
res54: scala.collection.immutable.Map[String,Int] = Map(ye -> 77, min -> 66, Greeye -> 99)

注意: 如何兩個陣列的元素個數不一樣,拉鍊的元組長度以較小的為準

四、集合

  • Scala 集合類系統地區分了可變的和不可變的集合。可變集合可以在適當的地方被更新或擴充套件。這意味著你可以修改,新增,移除一個集合的元素。而不可變集合類,相比之下,永遠不會改變。不過,你仍然可以模擬新增,移除或更新操作。但是這些操作將在每一種情況下都返回一個新的集合,同時使原來的集合不發生改變。

  • 所有的集合類都可以在包scala.collectionscala.collection.mutablescala.collection.immutablescala.collection.generic中找到。

  • 客戶端程式碼需要的大部分集合類都獨立地存在於3種變體中,它們位於scala.collection, scala.collection.immutable, scala.collection.mutable包。

  • scala.collection.immutable:包是的集合類確保不被任何物件改變。例如一個集合建立之後將不會改變。因此,你可以相信一個事實,在不同的點訪問同一個集合的值,你將總是得到相同的元素。
  • scala.collection.mutable:包的集合類則有一些操作可以修改集合。所以處理可變集合意味著你需要去理解哪些程式碼的修改會導致集合同時改變。
  • scala.collection:包中的集合,既可以是可變的,也可以是不可變的。例如:collection.IndexedSeq[T]](https://www.scala-lang.org/api/current/scala/collection/IndexedSeq.html) 就是 collection.immutable.IndexedSeqT 和collection.mutable.IndexedSeqT這兩類的超類。scala.collection包中的根集合類中定義了相同的介面作為不可變集合類,同時,scala.collection.mutable包中的可變集合類代表性的添加了一些有輔助作用的修改操作到這個immutable 介面。

預設情況下,Scala 一直採用不可變集合類。例如,如果你僅寫了Set 而沒有任何加字首也沒有從其它地方匯入Set,你會得到一個不可變的set,另外如果你寫迭代,你也會得到一個不可變的迭代集合類,這是由於這些類在從scala中匯入的時候都是預設繫結的。為了得到可變的預設版本,你需要顯式的宣告collection.mutable.Set或collection.mutable.Iterable.

一個有用的約定,如果你想要同時使用可變和不可變集合類,只匯入collection.mutable包即可。

import scala.collection.mutable  //匯入包scala.collection.mutable

集合樹的最後一個包是collection.generic。這個包包含了集合的構建塊。集合類延遲了collection.generic類中的部分操作實現,另一方面集合框架的使用者需要引用collection.generic中類在異常情況中。
為了方便和向後相容性,一些匯入型別在包scala中有別名,所以你能通過簡單的名字使用它們而不需要import。這有一個例子是List 型別,它可以用以下兩種方法使用,如下:

scala.collection.immutable.List // 這是它的定義位置
scala.List //通過scala 包中的別名
List // 因為scala._ // 總是是被自動匯入。

1、Seq

  • 不可變的序列 import scala.collecion.immutable

在Scala中列表要麼為空(Nil表示空列表)要麼是一個head元素加上一個tail列表。
List的操作符有 :: +: ++
其中 :: +: 是針對元素插入列表 ++是列表 加 列表
另外 :: 符號是右結合的方式,
比如9 :: 5 :: 2 :: Nil相當於 9 :: (5 :: (2 :: Nil))

object SeqTest{
  def main(args: Array[String]): Unit = {
    // 建立一個不可變的集合
    val lit1 = List(1,2,3)
    // 將0插入到集合List1的前面生成一個新的list  ::
    val lit2 = 0 :: lit1
    // 插入列表2  .::
    val lit3 = lit1.::(4)
    // 插入列表3 0+=
    val lit4 = 0 +: lit1
    // 插入列表4 .+:
    val lit5 = lit1.+: (0)
    println("lit1="+lit1)
    println("lit2="+lit2)
    println("lit3="+lit3)
    println("lit4="+lit4)
    println("lit4="+lit5)

    // 將4 插入到集合list1的後面生成一個新的list
    val lit6 = lit1 :+ 4
    println("lit6= "+lit6)

    //將2個List集合合併成一個新的list集合
    val list0 = List(7,8,9)
    println("list0="+list0)
    // ++ 合併集合的符號
    val lit7 = lit1 ++ list0
    println("lit7="+lit7)

    // 將list0 插入到lit1 的前面生成一個新的集合
    val lit8 = list0 ++ lit1
    print("lit8="+lit8)
  }
}
  • 可變的序列 import scala.collection.mutable._
import scala.collection.mutable.ListBuffer

object MutableSqlTest{

  def main(args: Array[String]): Unit = {
    // 構建一個可變序列
    val lit1 = ListBuffer[Int](1,2,3)
    // 建立一個空的可變序列
    val lit2 = new ListBuffer[Int]

    val lit3 = ListBuffer[Int](elems = 4,5,6)
   // 向 list 中追加元素: 注意是在現有列表中追加,沒有生成新的集合
    lit1 ++= lit3  // ++=
    println("lit1 3="+lit1)

    // lit1和lit2合併成一個新的lit集合,注意:生成新的集合
    val lit4 = lit1 ++ lit2
    println("lit4="+lit4)

    // 將元素追加到lit1後面生成一個新的集合
    val lit5 = lit1 :+ 9
    // 將元素追加到lit1前面生成一個新的集合 
    // 在可變列表的前面加元素?
    //val lit6 =  lit1.::(8)
    println("lit5="+lit5)
  }
}

2、Set

  • 不可變set
import scala.collection.immutable.HashSet
object ImmutableSet{
  def main(args: Array[String]): Unit = {
    // 建立一個空的set
    val set1 = new HashSet[Int]()
    println("set1="+set1)
    // 將元素和set合併生成一個新的set,原有set不變  +
    val set2 = set1 + 4
    println("set2="+set2)
    // set集合元素不會重複
    val set3 = set1 ++ Set(5,6,7)
    println("set3="+set3)
    // set 元素 之間相加  ++
    val set4 = Set(4,5,6) ++ set3
    println("set="+set4)
  }
}
  • 可變set
import scala.collection.mutable
object MutableSet{
  def main(args: Array[String]): Unit = {
    // 建立一個可變的set
    val set1 = new mutable.HashSet[Int]()
    println("list1="+set1)
    // 向 set1 中新增元素
    set1+=4
    // add 等價於 +=
    set1.add(5)
    // 集合合併 ++=
    set1 ++=Set(6,7,8)
    println("Set1="+set1)

    // 刪除一個元素
    set1 -= 8
    set1.remove(7)
    println("set1="+set1)
  }
}

五、Lazy關鍵字

Scala 中使用關鍵字lazy來定義惰性變數,實現延遲載入(懶載入)
惰性變數只能是不可變變數,並且只有在呼叫惰性變數時,才會例項化這個變數

object ScalaLazyDemo {
  def init():String = {
    println("huangbo 666")
    return "huangbo"
  }

  def main(args: Array[String]): Unit = {
    lazy val name = init();
    println("666")
    println(name)
  }
}

在宣告name時,並沒有立即呼叫例項化方法initName(),而是在使用name時,才會呼叫例項化方法,並且無論縮少次呼叫,例項化方法只會執行一次。