集合简介
- Scala同时支持不可变集合和可变集合
- 两个主要的包:
不可变集合:scala.collection.immutable(类似java中数组)
可变集合: scala.collection.mutable (类似java中ArrayList)
- Scala默认采用不可变集合,对于几乎所有的集合类,Scala都同时提供了可变(mutable)和不可变(immutable)的版本
- Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质,在Scala中集合有可变(mutable)和不可变(immutable)两种类型。
可变集合继承关系一览图
不可变集合继承关系一览图
数组的定义
不变长度数组
var t: Array[Int] = new Array[Int](4)
//集合元素采用小括号访问
t(1) = 13 //赋值操作
for (i <- Range(0, t.length)) {
print(i + " -> " + t(i) + ",")
}
println()
var arr: Array[Int] = Array(1, 24, 4)
//不同的便利方式
for (element <- arr) {
print("element -> " + element + ",")
}
//输出
// 0 -> 0,1 -> 13,2 -> 0,3 -> 0
// element -> 1,element -> 24,element -> 4
可变长度数组
var buf = ArrayBuffer[Any](3, 2, 4)
//追加元素
buf.append(12)
//追加多个元素
buf.append(13, "abc", 20)
//重新赋值(修改)
buf(0) = 43
//添加元素后输出
for (e <- buf) {
print(e + ",")
}
println()
//删除元素
buf.remove(1)
//删除元素后输出
for (e <- buf) {
print(e + ",")
}
println()
// 输出
//初始化添加元素后: 43,2,4,12,13,abc,20,
//删除指定的元素后: 43,4,12,13,abc,20,
可变长度数组和不可变长度数组互转
PS:原数据并没有变化,只是返回的新对象和原对象不同
var array: Array[Int] = new Array[Int](4)
var buf = ArrayBuffer[Any](3, 2, 4)
//可变数组转定长数组 仅仅tArray是定长数组,buf对象没有变化
var tArray: Array[Any] = buf.toArray
//定长数组转可变数组 仅仅tBuf是可变数组,t对象么有变
var tBuf: mutable.Buffer[Int] = array.toBuffer
总结
- ArrayBuffer是变长数组,类似java的ArrayList
- val arr2 = ArrayBuffer[Int]() 也是使用的apply方法构建对象
- def append(elems: A*) { appendAll(elems) } 接收的是可变参数.
- 每append一次,arr在底层会重新分配空间,进行扩容,arr2的内存地址会发生变化,也就成为新的ArrayBuffer
多维数组定义
案例是定义一个二维数组,有个四个元素(一维数组),每个一维数组有五个元素
val array1 = Array.ofDim[Int](4, 5)
array1(1)(1) = 5
array1(2)(2) = 3
for (item <- array1) {
for (item2 <- item) {
print(item2 + "\t")
}
println()
}
// 输出
// 0 0 0 0 0
// 0 5 0 0 0
// 0 0 3 0 0
// 0 0 0 0 0
scala数组和Java中List互转
import scala.collection.{JavaConverters, mutable}
import scala.collection.mutable.ArrayBuffer
object ConvertDemo {
def main(args: Array[String]): Unit = {
var list = JavaConverters.bufferAsJavaListConverter(buf)
var list1: java.util.List[Any] = list.asJava
println(list1)
var buf1 = JavaConverters.asScalaBufferConverter(list1)
var buf11: mutable.Buffer[Any] = buf1.asScala
println(buf11)
}
}
元组(Tuple)
元组也是可以理解为一个容器,可以存放各种相同或不同类型的数据。
大致是将多个无关的数据封装为一个整体,其最大的特点灵活,对数据没有过多的约束
Ps:元组中最大只能有22个元素
object TupleDemo {
def main(args: Array[String]): Unit = {
var tup1 = 1 -> "one"
var tup2 = (1, 2, 3, 4, "five", tup1)
//->操作 最终都生成一个新的两个元素的
var tup3 = tup1 -> "元素1" -> "元素2" -> "元素3"
println("元组1:" + tup1)
println("元组2:" + tup2)
println("元组2-第一个元素:" + tup2._1)
println("元组2-第二个元素:" + tup2._2)
println("元组2-第三个元素:" + tup2._3)
println("元组2-第三个元素:" + tup2.productElement(2))
println("元组3:" + tup3)
print("元组3-使用迭代器遍历:")
var it = tup3.productIterator
it.foreach(x => print(x + ","))
println()
print("元组3-反转后使用迭代器遍历:")
tup3.swap.productIterator.foreach(x => print(x + ","))
}
# -> 该操作符最终生成一个两个元素的元组
# productElement方法底层就是使用了._x 的操作
元组1:(1,one)
元组2:(1,2,3,4,five,(1,one))
元组2-第一个元素:1
元组2-第二个元素:2
元组2-第三个元素:3
元组2-第三个元素:3
元组3:((((1,one),元素1),元素2),元素3)
元组3-使用迭代器遍历:(((1,one),元素1),元素2),元素3
元组3-反转后使用迭代器遍历:元素3,(((1,one),元素1),元素2)
列表(List)
Scala中的List 和Java List 不一样,在Java中List是一个接口,真正存放数据是ArrayList,而Scala的List可以直接存放数据,就是一个object,默认情况下Scala的List是不可变的,List属于序列Seq。
创建列表
var list: List[Int] = List(1, 2, 3)
添加元素
向列表中增加元素, 会返回新的列表/集合对象,原集合没有发生任何变化
PS:Scala中List元素的追加形式非常独特,和Java不一样
//定义一个集合
var list: List[Int] = List(1, 2, 3)
println("原集合打印: " + list)
list.iterator.foreach(x => print(x + ","))
println()
println("原集合的第一个元素: " + list(0))
//在集合头部增加一个元素
println("使用::和+: 列表在头部增加元素")
var list1 = list.::(5)
var list2 = list.+:(6)
println("list1: " + list1)
println("list2: " + list2)
//在集合尾部增加元素
var list3 = list :+ 6
var list4 = 5 +: list :+ 13
println("list对象使用:+ , 元素使用+:列表尾部部增加元素")
println("list3: " + list3)
println("list4: " + list4)
println("list4: " + (4 :: 5 :: Nil))
println("::运算符")
//:: 元素使用:: 运算符在首部添加元素,列表需要放在最后
var list5 = 6 :: 5 :: list :: Nil
var list6 = list.::(5).::(6)
println("list5: " + list5)
println("list6: " + list6)
println(":::运算符")
var list7 = 4 :: 5 :: 6 :: list ::: list ::: list
var list8 = list.:::(list).:::(list).::(6).::(5).::(4)
println("list7: " + list7)
println("list8: " + list8)
var o1: List[Int] = List(1, 1)
var o2: List[Int] = List(2, 2)
var o3: List[Int] = List(3, 3)
println("组合看执行顺序: " + (o3 :: list))
println("组合看执行顺序: " + (o2 ::: o3 :: list))
println("组合看执行顺序: " + (o1 :: o2 ::: o3 :: list))
println("组合看执行顺序: " + (list ::: o1 :: o2 ::: o3 :: list))
println("组合看执行顺序: " + (4 :: list ::: o1 :: o2 ::: o3 :: list))
运行结果
原集合打印: List(1, 2, 3)
1,2,3,
原集合的第一个元素: 1
使用::和+: 列表在头部增加元素
list1: List(5, 1, 2, 3)
list2: List(6, 1, 2, 3)
list对象使用:+ , 元素使用+:列表尾部部增加元素
list3: List(1, 2, 3, 6)
list4: List(5, 1, 2, 3, 13)
list4: List(4, 5)
::运算符
list5: List(6, 5, List(1, 2, 3))
list6: List(6, 5, 1, 2, 3)
:::运算符
list7: List(4, 5, 6, 1, 2, 3, 1, 2, 3, 1, 2, 3)
list8: List(4, 5, 6, 1, 2, 3, 1, 2, 3, 1, 2, 3)
组合看执行顺序: List(List(3, 3), 1, 2, 3)
组合看执行顺序: List(2, 2, List(3, 3), 1, 2, 3)
组合看执行顺序: List(List(1, 1), 2, 2, List(3, 3), 1, 2, 3)
组合看执行顺序: List(1, 2, 3, List(1, 1), 2, 2, List(3, 3), 1, 2, 3)
组合看执行顺序: List(4, 1, 2, 3, List(1, 1), 2, 2, List(3, 3), 1, 2, 3)
列表总结
运算符
数据获取
list(0)---- 获取第一个元素
PS:可以使用迭代器,或者是for循环进行遍历
:+ 和 +:
:+ 表示尾部增加元素
+: 表示头部增加元素
list 使用 :+ 在尾部增加数据
元素使用 +:在列表头部增加数据,等同与 list.+:(x) / list.::(x)
:: 等价为list.::(x)
表示向集合中添加元素,执行数序为从右到左
PS: 集合对象一定要放置到最右边,且至少右边有一个集合对象
:::等价为list.:::(x)
两个集合间的操作,将集合中的每一个元素加入到另一个集合中去
PS: 执行数序为从右到左,有且至少有个两个集合对象
列表(ListBuffer )
ListBuffer是可变的list集合,可以添加,删除元素,ListBuffer属于序列
val buffer = ListBuffer[Int](1, 2, 3)
println("buffer(2)=" + buffer(2))
print("输出可变集合: ")
for (item <- buffer) {
print(item + ", ")
}
println()
val buffer1 = new ListBuffer[Int]
//添加元素
buffer1 += 4
//追加元素
buffer1.append(7)
buffer1.append(5, 34, 3, 5)
//两个集合合并
val buffer2 = buffer ++ buffer1
//追加元素
val buffer3 = buffer :+ 5
println("buffer=" + buffer)
println("buffer1=" + buffer1)
println("buffer2=" + buffer2)
println("buffer3=" + buffer3)
//删除元素
buffer1.remove(1)
print("删除后输出可变集合: ")
for (item <- buffer1) {
print(item + ", ")
}
// 输出结果
buffer(2)=3
输出可变集合: 1, 2, 3,
buffer=ListBuffer(1, 2, 3)
buffer1=ListBuffer(4, 7, 5, 34, 3, 5)
buffer2=ListBuffer(1, 2, 3, 4, 7, 5, 34, 3, 5)
buffer3=ListBuffer(1, 2, 3, 5)
删除后输出可变集合: 4, 5, 34, 3, 5,
队列(Queue)
- 队列是一个有序列表,在底层可以用数组或是链表来实现。
- 其输入和输出要遵循先入先出的原则。即:先存入队列的数据,要先取出。后存入的要后取出
- 在Scala中,由设计者直接给我们提供队列类型使用。
- 在scala中, 有 scala.collection.mutable.Queue 和 scala.collection.immutable.Queue , 一般来说,我们在开发中通常使用可变集合中的队列。
//创建队列对象
var q1 = new mutable.Queue[Int]
//增加一个元素
q1 += 20
//两个集合连接声明一个新的集合(原集合不变)
var q2 = q1 ++ List(1, 23)
//增加一个集合 并重复赋值给当前对象
q1 ++= List(1, 23)
println("++=之后: " + q1)
println("++赋值给其他集合后: " + q2)
println("第一元素:" + q1.head)
println("最后元素:" + q1.last)
//去除第一个之后的队列对象
println("尾部对象(去除首个元素):" + q1.tail)
//删除一个元素
q2.dequeue()
q2.dequeueAll(x => x > 3)
println("删除元素之后: " + q2)
//增加元素
q2.enqueue(20, 23)
println("删除并增加元素之后: " + q2)
// 输出
++=之后: Queue(20, 1, 23)
++赋值给其他集合后: Queue(20, 1, 23)
第一元素:20
最后元素:23
尾部对象(去除首个元素):Queue(1, 23)
删除元素之后: Queue(1)
删除并增加元素之后: Queue(1, 20, 23)
映射(Map)
- Scala中的Map 和Java类似,也是一个散列表,它存储的内容也是键值对(key-value)映射,Scala中不可变的Map是有序的,可变的Map是无序的。
- Scala中,有可变Map (scala.collection.mutable.Map) 和 不可变Map(scala.collection.immutable.Map)
创建map方式
1.直接创建
注意点:
- 集合中的元素实际就是Tuple2类型;
- 不可变map是有序的;
- 可变map是无序的;
- 默认没有引包的情况下Map是不可变Map
//创建map的方式
//1. 直接声明可变或者是不可变map
val map1 = scala.collection.mutable.Map("AAA" -> 1, "BBB" -> 2, "CCC" -> 3) //可变
//总结:不可变map是有序的;集合中的元素实际就是Tuple2类型;默认没有引包的情况下Map是不可变Map
val map2 = scala.collection.immutable.Map("AAA" -> 1, "BBB" -> 2, "CCC" -> 3) //不可变
2.使用new关键字创建
PS:对于可变map能做一些业务逻辑,如果创建一个空的不可变map用处不大
//2.使用new关键字创建空的map
val map3 = new mutable.HashMap[String, Int]() //可变
val map4 = new HashMap[String, String]() //不可变
3.对偶元组(和第一种创建方式等价)
val map5 = mutable.Map(("AAA", "aaa"), ("BBB", "bbb")) //可变
val map6 = Map(("AAA", "aaa"), ("BBB", "bbb")) // 不可变(默认使用的是不可变的map)
Map元素操作
PS:
- 元素新增、修改、删除真对于可变map
- 添加元素时,如果当前key不存在就新增,如果已经存在就修改
- 删除元素时,如果key不存在不会报错
// 只有可变的map才能修改、增加、删除元素
// 添加元素,如果key已经存在就修改,如果不存在就添加
map3("AAA") = 1
map3 += ("AAA" -> 44) //添加一个元素(如果已经存在该key相当于修改)
map3 += ("BBB" -> 11, "CCC" -> 22) //添加多个元素
println("添加元素之后的map: " + map3)
map3 -= ("FFF") //key如果存在就直接删除,如果不存在也不会报错
map3 -= ("DDD", "CCC") // 可以支持删除多个key
map元素的获取
- map("key") :没有对应的key会报错
- map.get("key").get :没有对应的key会获取到None,会报错
- map.getOrElse("key","默认值") :没有对应的key会返回默认值
PS: 因为不存在key会报错,可以使用map.contains("key")判断存在再获取
//获取元素的方式
println("map获取值")
// 如果没有对应的key会报错
println("map获取值-1: map3(\"AAA\")= " + map3("AAA"))
// 如果没有对应的key会产生None,然后会报.NoSuchElementException
println("map获取值-2: map3.get(\"AAA\").get= " + map3.get("AAA").get)
//如果对应的key能取到值就返回该值,否则就返回对应的默认值
println("map获取值-3:map3.getOrElse(\"AAAC\", -1)= " + map3.getOrElse("AAAC", -1))
println("包含key判断:map3.contains(\"AAA\")= " + map3.contains("AAA"))
map遍历
// 遍历map对象
println("遍历map")
println("遍历map-1: 使用key,value遍历map")
for ((k, v) <- map3) print(k + " = " + v + ", ")
println()
println("遍历map-2: 遍历map的key")
for (k <- map3.keys) print(k + ", ")
println()
println("遍历map-3: 遍历map的value")
for (k <- map3.values) print(k + ", ")
println()
println("遍历map-4: 遍历map的中的对象")
for (k <- map3) print(k + ", ")
println()
println("遍历map-5: 使用foreach遍历")
map3.foreach(e => print(e._1 + " - " + e._2 + ", "))
集合(Set)
集是不重复元素的结合。集不保留顺序,默认是以哈希集实现
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包
集合创建
//不可变集合
val set1 = Set(1, 2, 3)
//可变集合
val set2 = scala.collection.mutable.Set(4, 5, 6, "")
//可变空集合
val set3 = new mutable.HashSet[Int]()
集合操作
//添加操作,如果元素已经存在不做任何处理,也不报错
set3.add(11)
set3 += 22
set3.+=(33)
//删除操作
set3 -= 22
set3.-=(22)
set3.remove(44)
set3.foreach(x => print(x))
//直接操作+ - 会产生新集合,原集合不变
val set4 = set3 + 5
val set5 = set3 - 33
set3 += 113
//集合1连接集合2(原集合不变)
val set6 = set3 ++ set4
//集合1减去集合2(原集合不变)
val set7 = set3 -- set4
println()
println("set3: " + set3)
println("set3max: " + set3.max)
println("set3min: " + set3.min)
println("set4: " + set4)
println("set5: " + set5)
println("set6: " + set6)
println("set7: " + set7)
集合遍历
println("遍历集合: ")
for (x <- set3) {
print(x + ", ")
}
println()
set3.foreach(x => print(x + ", "))