5、Scala 集合相关
5.1、Scala 集合
Scala 的集合有三大类:序列 Seq、集合 Set、映射 Map,所有的集合都扩展自 Iterable 特质 在 Scala 中集合有可变(mutable)和不可变(immutable)两种类型,immutable 类型的集合
初始化后就不能改变了(注意与 val 修饰的变量进行区别)
官网解释: Scala collections systematically distinguish between mutable and immutable collections. A mutable collection can be updated or extended in place. This means you can change, add, or remove elements of a collection as a side effect. Immutable collections, by contrast, never change. You have still operations that simulate additions, removals, or updates, but those operations will in each case return a new collection and leave the old collection unchanged.
//大致意思是:Scala 中的集合分为两种,一种是可变的集合,另一种是不可变的集合
//可变的集合可以更新或修改,添加、删除、修改元素将作用于原集合
//不可变集合一量被创建,便不能被改变,添加、删除、更新操作返回的是新的集合,老集 合保持不变
val 和 var:表明定义的变量(引用)是否能被修改而指向其他内容 immutable 和 mutable:表明的是内存中开辟出来的这块空间里的内容能否被修改,如果针 对 immutable 变量进行修改,其实是开辟了一块新的内存空间,产生了一个新的变量,而 原来的变量依然没有改变
5.2、Scala 序列--List
不可变的序列 import scala.collection.immutable._
在 Scala 中列表要么为空(Nil 表示空列表)要么是一个 head 元素加上一个 tail 列表。
9 :: List(5, 2) :: 操作符是将给定的头和尾创建一个新的列表
注意::: 操作符是右结合的,如 9 :: 5 :: 2 :: Nil 相当于 9 :: (5 :: (2 :: Nil))
package com.mazh.scala.core
object ImmutableListDemo {
def main(args: Array[String]) {
// 创建一个不可变的集合 val lst1 = List(1,2,3)
// 将 0
插入到 lst1
的前面生成一个新的 List
val lst2 = 0 :: lst1
val lst3 = lst1.::(0)
val lst4 = 0 +: lst1
val lst5 = lst1.+:(0)
// 将一个元素添加到 lst1的后面产生一个新的集合
val lst6 = lst1 :+ 3
val lst0 = List(4,5,6)
// 将 2个 list合并成一个新的 List
val lst7 = lst1 ++ lst0
// 将 lst0插入到 lst1前面生成一个新的集合
val lst8 = lst1 ++: lst0
// 将 lst0插入到 lst1前面生成一个新的集合
val lst9 = lst1.:::(lst0)
println(lst9)
}
}
序列常用操作:
//采用::及 Nil 进行列表构建
scala> val nums = 1 :: (2 :: (3 :: (4 :: Nil)))
nums: List[Int] = List(1, 2, 3, 4)
//由于::操作符的优先级是从右往左的,因此上一条语句等同于下面这条语句
scala> val nums=1::2::3::4::Nil
nums: List[Int] = List(1, 2, 3, 4)
//判断是否为空
scala> nums.isEmpty res108: Boolean = false
//取第一个无素
scala> nums.head res109: Int = 1
//取除第一个元素外剩余的元素,返回的是列表
scala> nums.tail res114: List[Int] = List(2, 3, 4)
//取列表第二个元素
scala> nums.tail.head res115: Int = 2
//插入排序算法实现
def isort(xs: List[Int]): List[Int] = if (xs.isEmpty) Nil
else insert(xs.head, isort(xs.tail))
def insert(x: Int, xs: List[Int]): List[Int] = if (xs.isEmpty || x <= xs.head) x :: xs else xs.head :: insert(x, xs.tail)
//List 连接操作 scala> List(1,2,3):::List(4,5,6) res116: List[Int] = List(1, 2, 3, 4, 5, 6)
//取除最后一个元素外的元素,返回的是列表 scala> nums.init res117: List[Int] = List(1, 2, 3)
//取列表最后一个元素 scala> nums.last res118: Int = 4
//列表元素倒置 scala> nums.reverse res119: List[Int] = List(4, 3, 2, 1)
//一些好玩的方法调用 scala> nums.reverse.reverse==nums res120: Boolean = true
scala> nums.reverse.init res121: List[Int] = List(4, 3, 2)
scala> nums.tail.reverse res122: List[Int] = List(4, 3, 2)
//丢弃前 n 个元素 scala> nums drop 3 res123: List[Int] = List(4)
scala> nums drop 1 res124: List[Int] = List(2, 3, 4)
//获取前 n 个元素 scala> nums take 1 res125: List[Int] = List(1)
scala> nums.take(3)
res126: List[Int] = List(1, 2, 3)
//将列表进行分割 scala> nums.splitAt(2) res127: (List[Int], List[Int]) = (List(1, 2),List(3, 4))
//前一个操作与下列语句等同 scala> (nums.take(2),nums.drop(2)) res128: (List[Int], List[Int]) = (List(1, 2),List(3, 4))
//Zip 操作 scala> val nums=List(1,2,3,4) nums: List[Int] = List(1, 2, 3, 4)
scala> val chars=List('1','2','3','4') chars: List[Char] = List(1, 2, 3, 4)
//返回的是 List 类型的元组(Tuple) scala> nums zip chars res130: List[(Int, Char)] = List((1,1), (2,2), (3,3), (4,4))
//List toString 方法 scala> nums.toString res131: String = List(1, 2, 3, 4)
//List mkString 方法 scala> nums.mkString res132: String = 1234
//转换成数组 scala> nums.toArray res134: Array[Int] = Array(1, 2, 3, 4)
可变的序列
import scala.collection.mutable._
package com.mazh.scala.core
import scala.collection.mutable.ListBuffer
object MutableListDemo extends App{
// 构建一个可变列表,初始有 3个元素 1,2,3
val lst0 = ListBuffer[Int](1,2,3)
// 创建一个空的可变列表
val lst1 = new ListBuffer[Int]
// 向 lst1中追加元素,注意:没有生成新的集合
lst1 += 4
lst1.append(5)
// 将 lst1中的元素最近到 lst0中, 注意:没有生成新的集合
lst0 ++= lst1
// 将 lst0和 lst1合并成一个新的 ListBuffer 注意:生成了一 个集合
val lst2= lst0 ++ lst1
// 将元素追加到 lst0的后面生成一个新的集合
val lst3 = lst0 :+ 5
}
5.3、Scala 集合--Set
不可变的 Set
package com.mazh.scala.core
import scala.collection.immutable.HashSet
object ImmutableSetDemo extends App{
val set1 = new HashSet[Int]()
// 将元素和 set1合并生成一个新的 set ,原有 set不变
val set2 = set1 + 4
//set中元素不能重复
val set3 = set1 ++ Set(5, 6, 7)
val set0 = Set(1,3,4) ++ set1
println(set0.getClass)
}
可变的 Set
package com.mazh.scala.core
import scala.collection.mutable
object MutableSetDemo extends App{
// 创建一个可变的 HashSet
val set1 = new mutable.HashSet[Int]()
// 向 HashSet中添加元素
set1 += 2
//add等价于 +=
set1.add(4)
set1 ++= Set(1,3,5)
println(set1)
// 删除一个元素
set1 -= 5
set1.remove(2)
println(set1)
}
怎么求集合的交集并集差集呢?
5.4、Scala 集合--Map
package com.mazh.scala.core
import scala.collection.mutable
object MutableMapDemo extends App{
val map1 = new mutable.HashMap[String, Int]()
// 向 map中添加数据
map1("spark") = 1
map1 += (("hadoop", 2))
map1.put("storm", 3)
println(map1)
// 从 map中移除元素
map1 -= "spark"
map1.remove("hadoop")
println(map1)
}
5.5、Scala 映射—Map
在 Scala 中,把哈希表这种数据结构叫做映射,在 Java 中也叫做映射 在 Python 中,把哈希表这种数据结构叫做字典 不管叫什么,存储的都是键值对形式的值
5.5.1、构建 Map
5.5.2、获取和修改 Map 中的值
好用的 getOrElse
注意:在 Scala 中,有两种 Map,一个是 immutable 包下的 Map,该 Map 中的内容不可变;
另一个是 mutable 包下的 Map,该 Map 中的内容可变 例子:
注意:通常我们在创建一个集合是会用val这个关键字修饰一个变量(相当于java中的final),
那么就意味着该变量的引用不可变,该引用中的内容是不是可变,取决于这个引用指向的 集合的类型
Map 常用操作:
scala> val studentInfo=Map("john" -> 21, "stephen" -> 22,"lucy" -> 20)
studentInfo: scala.collection.immutable.Map[String,Int] = Map(john -> 21, stephen -> 22, lucy -> 20)
scala> studentInfo.clear()
<console>:13: error: value clear is not a member of scala.collection.immutable.Map[String,Int]
studentInfo.clear()
^
scala> val studentInfoMutable=scala.collection.mutable.Map("john" -> 21, "stephen" -> 22,"lucy" -> 20)
studentInfoMutable: scala.collection.mutable.Map[String,Int] = Map(john -> 21, lucy -> 20, stephen -> 22)
scala> studentInfoMutable.clear()
scala> studentInfoMutable
res2: scala.collection.mutable.Map[String,Int] = Map()
scala> for( i <- studentInfoMutable ) println(i)
scala> val studentInfoMutable=scala.collection.mutable.Map("john" -> 21, "stephen" -> 22,"lucy" -> 20)
studentInfoMutable: scala.collection.mutable.Map[String,Int] = Map(john -> 21, lucy -> 20, stephen -> 22)
scala> for( i <- studentInfoMutable ) println(i)
(john,21)
(lucy,20)
(stephen,22)
scala> studentInfoMutable.foreach(e=> println(e._1+":"+e._2))
john:21
lucy:20
stephen:22
scala> val xMap=new scala.collection.mutable.HashMap[String,Int]()
xMap: scala.collection.mutable.HashMap[String,Int] = Map()
scala> xMap.put("spark",1)
res6: Option[Int] = None
scala> xMap.put("spark",1)
res7: Option[Int] = Some(1)
scala> xMap.contains("spark")
res8: Boolean = true
scala> val xMap=scala.collection.mutable.Map(("spark",1),("hive",1))
xMap: scala.collection.mutable.Map[String,Int] = Map(spark -> 1, hive -> 1)
scala> "spark" -> 1
res9: (String, Int) = (spark,1)
scala> xMap.get("spark")
res10: Option[Int] = Some(1)
scala> xMap.get("SparkSQL")
res11: Option[Int] = None
Option, None, Some 类型
Option、None、Some 是 scala 中定义的类型,它们在 scala 语言中十分常用,因此这三个类 型非学重要。
None、Some 是 Option 的子类,它主要解决值为 null 的问题,在 java 语言中, 对于定义好的 HashMap,
如果 get 方法中传入的键不存在,方法会返回 null,在编写代码的 时候对于 null 的这种情况通常需要特殊处理,
然而在实际中经常会忘记,因此它很容易引起 NullPointerException 异常。在 Scala 语言中通过 Option、None、
Some 这三个类来避免这样 的问题,这样做有几个好处,首先是代码可读性更强,当看到 Option 时,
我们自然而然就 知道它的值是可选的,然后变量是 Option,比如 Option[String]的时候,直接使用 String 的话,
编译直接通不过。
5.6、Scala 元组--Tuple
映射是 K/V 对偶的集合,对偶是元组的最简单形式,元组可以装着多个不同类型的值。
5.6.1、创建元组
5.6.2、获取元组中的值
5.6.3、将对偶的元组转成集合
5.6.4、元组拉链操作
zip 命令可以将多个值绑定在一起
注意:如果两个数组的元素个数不一致,拉链操作后生成的数组的长度为较小的那个数组的 元素个数