Scala 学习笔记(三) Scala的数组、映射、元组、集合、关键字Lazy

文章目录

      • 一、数组
        • 1、定长数组和可变数组
        • 2、遍历数组
        • 3、数组转换
        • 4、常用数组的属性
      • 二、映射(Map)
        • 1、构建映射的方式
        • 2、获取映射的值
      • 三、元组
        • 1、创建元组
        • 2、获取元组中的值
        • 3、将对偶元组转换成映射
        • 4、zip拉链操作
      • 四、集合
        • 1、Seq
        • 2、Set
      • 五、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时,才会调用实例化方法,并且无论缩少次调用,实例化方法只会执行一次。

你可能感兴趣的:(Scala)