Scala的集合系统

2023-10-18 大数据Scala

首先来看一下整体的结构图,和Java不一样的是,Scala分为可变集合和不可变集合。

  • 可变集合:在scala.collection.mutable这个包下面
  • 不可变集合:在scala.collection.immutable这个包下面

  • 我们在创建集合的时候,如果不指定具体的包名,默认会使用不可变集合,不可变集合在初始化后无法修改。

Iterable

# Set集合的使用

Set集合分为可变的和不可变的集合,默认情况下使用的是不可变集合,定义方式:val s = Set(1,2,3)

val s = Set(1,2,3)
s += 4 // 会报错,因为默认创建的是不可变集合
s + 4 // 可以正常输出,因为创建了新的集合

创建可变集合:

val s = scala.collection.mutable.Set(1,2,3)
s += 4

# Set集合的子类

Set常用子类有: HashSet、LinkedHashSet、SortedSet。

  • HashSet:元素不重复、无序
  • LinkedHashSet:集合中的元素不重复、有序,它会用一个链表维护插入顺序, 可以保证集合中元素是有序的
  • SortedSet:集合中的元素不重复、有序,它会自动根据元素来进行排序
  • 如果在创建集合的时候就初始化了元素,则可以省略泛型的定义,集合会自动识别元素的类型
// 1.使用HashSet,可以new也可以不new,因为HashSet既是class又是object,但是包名需要指定
val s = new scala.collection.mutable.HashSet[Int]()
// 2.使用LinkedHashSet
val s = new scala.collection.mutable.LinkedHashSet[Int]()
s += 1
s += 5
s += 2
print(s)

最后再来看一下SortedSet

// 使用SortedSet,不可以使用new
val s = scala.collection.mutable.SortedSet[String]()
s += ("c")
s += ("a")
s += ("b")

scala> print(s)
TreeSet(a, b, c)

# for循环迭代

scala> for (i <- s) print(i + "\t")
a       b       c

# List集合的使用

List代表一个不可变的列表,属于Seq接口的子接口。

val list1 = List(1, 2, 3, 4)

针对List有headtail以及::这几个操作:

  1. head:返回列表的第一个元素。如果列表为空,则抛出异常。
  2. tail:返回除第一个元素外的其他元素组成的新列表,如果列表为空,则返回空列表。
  3. :::用于将一个元素添加到列表的开头。它是一个二元操作符,左边是要添加的元素,右边是原始列表。例如1 :: Nil表示一个只包含元素1的新列表。
scala> list1.head
res10: Int = 1

scala> list1.tail
res11: List[Int] = List(2, 3, 4)

scala> list1.head :: list1.tail
res12: List[Int] = List(1, 2, 3, 4)

scala> for(i <- list1) print(i+"\t")
1       2       3       4

# ListBuffer

List作为不可变集合在工作中用起来很不方便,ListBuffer支持动态添加和移除元素。

scala> val list2 = scala.collection.mutable.ListBuffer[Int]()
list2: scala.collection.mutable.ListBuffer[Int] = ListBuffer()

scala> list2 +=  1
res14: list2.type = ListBuffer(1)

scala> list2 += 2
res15: list2.type = ListBuffer(1, 2)

scala> list2 -= 2
res16: list2.type = ListBuffer(1)

# Map集合的使用

Map是一种可迭代的键值对(key/value)结构,

// 创建不可变Map
val ages = Map("jack"->30,"tom"->25,"jessic"->23)
ages("jack")

// 创建不可变Map集合写法2
val ages = Map(("jack", 30), ("tom", 25), ("jessic", 23))
ages("jack")

// 遍历
for((key, value) <- ages) println(key + ":" + value)
// 遍历key
for(key <- ages.keys) println(key)
// 遍历value
for(v <- ages.values) println(v)

可变Map集合有一些常用操作:

  1. put(key, value):向Map中添加一个键值对。如果Map中已存在该键,则旧值将被替换。
  2. get(key):根据键获取对应的值。如果Map中不存在该键,则返回None。
  3. remove(key):删除Map中的某个键值对,并返回被删除的值。如果Map中不存在该键,则返回None。
  4. keys/keySet:获取Map中所有的键,返回一个包含所有键的集合。
  5. values:获取Map中所有的值,返回一个包含所有值的集合。
  6. contains:查询map的key是否存在
  7. getOrElse:如果key存在则赋值,否则有个默认值
  8. foreach { case (key, value) => }:遍历Map中的每一个键值对,对每一个元素执行给定的操作。
// 创建可变Map集合
scala> val map1 = scala.collection.mutable.Map("jack"->30,"tom"->25,"jessic"->23)
map1: scala.collection.mutable.Map[String,Int] = Map(jessic -> 23, jack -> 30, tom -> 25)

// 新增
scala> map1.put("key1",70)
res19: Option[Int] = None

// 修改
scala> map1("key1") = 99

// 移除
scala> map1 -= "key1"

scala> map1("key2") // 查询不存在的key会报错
java.util.NoSuchElementException: key not found: key2
  at scala.collection.MapLike.default(MapLike.scala:236)
  at scala.collection.MapLike.default$(MapLike.scala:235)
  at scala.collection.AbstractMap.default(Map.scala:65)

// 判断Key是否存在
scala> map1.contains("key2")
res22: Boolean = false

 // 如果key存在则赋值,否则默认值为0
scala> val age = if (map1.contains("key1")) map1("key1") else 0
age: Int = 70

// 更简答的写法
scala> val age = map1.getOrElse("key1", 12)
age: Int = 70

// 增加多个元素
map1 += ("zhangsan" -> 92, "lisi" -> 18)

# Map集合的子类

  • HashMap:是一个按照key的hash值进行排列存储的map
  • SortedMap:不可变,可以自动对Map中的key进行排序【有序的map】
  • LinkedHashMap:可变,可以记住插入的key-value的顺序
// 创建SortedMap
scala> val ages1 = scala.collection.mutable.SortedMap("b" -> 30, "a" -> 29)
ages1: scala.collection.mutable.SortedMap[String,Int] = TreeMap(a -> 29, b -> 30)

// 创建LinkedHashMap
scala> val ages2 = new scala.collection.mutable.LinkedHashMap[String, Int]()
ages2: scala.collection.mutable.LinkedHashMap[String,Int] = Map()

scala> ages2("b") = 30
scala> ages2("a") = 19
scala> ages2("c") = 17
scala> print(ages2)
Map(b -> 30, a -> 19, c -> 17)

# Array数组的使用

Array和Java的数组类似,长度不可变,Scala数组的底层实际上就是Java数组,双方可以互相调用。

scala> val a  = new Array[Int](10)
a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

scala> a(0)
res39: Int = 0

scala> a(0)=1

scala> a(0)
res41: Int = 1

也可以直接使用Array()创建数组,元素类型自动推断。

scala> val a = Array("hello", "world")
a: Array[String] = Array(hello, world)

scala> a(0)
res42: String = hello

# ArrayBuffer

与Java中的ArrayList类似,长度可变,支持添加元素、移除元素,如果不想每次都使用全限定名,则可以预先导入ArrayBuffer类。

import scala.collection.mutable.ArrayBuffer

定义一个空的ArrayBuffer,使用+=添加元素,可以添加多个。

scala> val b = new ArrayBuffer[Int]()
b: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

scala> b += 1
res44: b.type = ArrayBuffer(1)

scala> b += (2, 3, 4, 5)
res45: b.type = ArrayBuffer(1, 2, 3, 4, 5)

使用insert()函数可以在指定位置插入元素,但是这种操作效率很低,因为需要移动指定位置后的所有元素。remove()可以删除元素。

scala> b.insert(3, 30)

scala> print(b)
ArrayBuffer(1, 2, 3, 30, 4, 5)

scala> b.remove(3) // remove按照下标进行删除
res48: Int = 30

scala> print(b)
ArrayBuffer(1, 2, 3, 4, 5)

注意:Array与ArrayBuffer可以互相进行转换,b.toArraya.toBuffer

# 数组常见操作

求和、求最大值、数组排序

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

scala> val sum = a.sum
sum: Int = 15

scala> val max = a.max
max: Int = 5

// 排序
scala> scala.util.Sorting.quickSort(a)

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

# Tuple

Tuple称为元组,与Array类似,都是不可变的,但与数组不同的是元组可以包含不同类型的元素,Tuple中的元素角标从1开始。

scala> val t = (1, 3.14, "hehe")
t: (Int, Double, String) = (1,3.14,hehe)

scala> t._1
res52: Int = 1

scala> t._2
res53: Double = 3.14

注意:目前 Scala 支持的元组最大长度为 22 ,对于更大长度可以使用集合或数组。

上次更新: 4 个月前