集合
集合简介
1. Scala的集合有三大类:序列Seq、集set、映射Map,所有的集合都扩展自Iterable特质。
- 对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于下面两个包{不可变集合:scala.collection.immutable
可变集合:scala.collection.mutable}。
- Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于Java中的String对向。
- 可变集合,就是这个对象可以对原对向进行修改,而不会返回新的对象。类似于Java中的StringBuilder对象。
建议:在操作集合的时候,不可变用符号,可变用方法
不可变数组
第一种定义数组方式
val arr1=new Array[Int](10)
arr1是数组名称,new是关键字。[Int]是指定可以存放的数据类型,如果希望存放任意数据类型,则指定Any。(10),表示数组的大小,确定后不可变。
另一种创建方式
val arr2=Array(12,13,14,15,16)
创建数组的时候将所有的数据添加进去,这样会简便高效
给元素赋值
创建数组,但未给赋值时,Int类型默认为0
arr1(0) = 12
访问元素
println( arr1 (0) )
普通for循环
for (i<- 0 until arr2.length){ //to方法没办法遍历到length-1位
print(arr2(i)+",")
用Scala自带方法的for循环
for (i<- arr2.indices) {
print(arr2(i)+",")
增强for循环,直接遍历所有元素
for (i <- arr2) println(i)
迭代器
val iter = arr2.iterator
hile (iter.hasNext)
println(iter.next())
调用foreach()方法
arr2.foreach( (i:Int) => println(i) )
将数组中所有元素连接起来,变为字符串打印出来
println ( arr2.mkString ("") ) //元素之间用什么连接,就将中间的放在引号里面
添加元素
因为数组不可变,所以添加元素的是返回出来的新数组
val arr3 = arr2 . : + (75) //旧数组后加小数点,冒号和加号
(加号在冒号后面,表示添加元素在数组最后,加号在冒号前面,表示添加元素在数组前面)
val arr4 = arr2.+:(56)
Scala中另一种写法
val arr5 = arr2 :+ 78 //加数组后面
val arr5 = 19 +: 29 +: arr2 :+ 78 //前面加两个,后面加一个,冒号和加号记得换位
可变数组
创建可变数组,两种方法
val arr1: ArrayBuffer[Int] = new ArrayBuffer[Int]() //创建单一个数组
val arr2 = ArrayBuffer(23,57,93) //简便
访问元素
println(arr2(2)) //与不可变一样
遍历等操作与上述一样
添加元素
可变数组一般不用:+的操作,因为这个操作需要创建新的对象
arr2 += 12 //在集合后面加
77 +=:arr2 //在集合前面加
(一般不要用可变数组为基础创建一个新集合,这样创建出来的集合在一个地址,在新集合或者旧集合添加元素时,两个集合都会出现新元素)
用方法在集合加元素
arr2.append(36)
arr2.prepend(11,76)
删除元素
arr2.remove(3) //3是位置
arr2.remove(3,10) //是从3位置删到10位置
arr2 -= 13 //删除13这个数,有删,没有什么都不做
数组转换
可变数组转换为不可变数组
val arr:ArrayBuffer[Int] = ArrayBuffer(23,56,98)
val newArr: Array[int]= arr.toArray //调用toArrag方法
不可变数组转换为可变数组
val buffer:mutable.BUffer[Int] = newArr . toBuffer //调用toBuffer方法
创建二维数组
val array:Array[Array[Int]] = Array.ofDim[Int](n1=2,n2=3)
- val array: Array[Array[Int]]:定义一个名为array的变量,类型为Array[Array[Int]],即一个二维整数数组。
- Array.ofDim[Int]:这是Scala中的一个方法,用于创建一个指定维度和类型的数组。在这里,我们使用ofDim方法创建一个二维整数数组。
- (n1=2, n2=3):这是ofDim方法的参数,表示创建的二维数组的行数(n1)和列数(n2)。在这个例子中,我们创建了一个2行3列的二维整数数组。
访问二维数组的元素
array(0)(1)
赋值(更改)二维数组的元素
array(0)(1) = 18
用for循环遍历二维数组
for (i<-0 until array.length; j<-0 until array(i).length){
println(array( i ) ( j) )
for循环先是将行类循环,再循环竖列,打印出来为一竖列
for (i<-array.indices;j<-array(i).indices){
print(array(i)(j)+"\t") //更加规范,打印出来为数表形式
if(j==array(i).length-1)println()
用foreach方法实现
array.foreach(line => line.foreach(println))
二维有两个foreach,三维有三个foreach等等
列表List
不可变列表list
val list1 = List(23,24,45) //List第一个字母大写
索引
println( list1 (1) )
遍历与数组的大体一样
向列表中添加元素
val list2 = list1.+:(10)
val list3 = list1 :+ 23
与不可变数组的添加方式几乎一样
list的独有添加方式,可以用于创建列表
val list4 = list2.::(89) //在列表前面添加89
val list5 = 19 :: 18 :: 17 :: 16 :: Nil //创建list5列表,顺序是从16到19
列表的合并
val list6 = list1 ::: list5 //三个冒号连接两个列表,可以合并两列表
val list7 = list1 ++ list5 //两个加号连接也可以
可变的列表
val list1: ListBuffer[Int] = new ListBuffer[Int]()
val list2 = ListBuffer(12,34,45,56)
添加元素
list2.append(15,23)
list2.prepend(20)
list2.insert(2,19,22) //第一个数2是位置
31 +=: 98 +=: list1 += 23 += 41
合并两个list
val list3 = list1 ++ list2 //list1和list2不变
修改元素
list2(3) = 30
删除元素
list2.remove(2) //索引删除
list2 -= 24 //具体数值删除
groupBy
是一个用于将列表中的元素按照指定条件进行分组的方法,这个方法接收一个函数作为参数,这个函数定义了分组的条件。groupBy方法返回一个Map,其中Map的键(key)是根据分组条件得到的结果,而值(value)是满足该条件的元素组成的列表。
val map1:Map[String,List[String]]=list2.groupBy(word=>word)
word=>word //意味着列表中的元素根据自身的值进行分组
Set集合
因为可变set和不可变set都是set,所以使用set时要指明哪里的set
不可变set
创建set
val set1 = Set(12,34,45,77,77) //重复的会被删除
添加元素
val set2 = set1.+(20)
val set2 = set1 + 20 //更加简便
合并set
val set4 = set2 ++ set3
删除元素
val set5 = set3 - 3 //set3不变,set5比set3少3
可变的set
创建set
import scala.collection.mutable //导包可以用
val set1 = mutable.Set(12,23,34,45,56)
添加元素
set1 += 11
set1.add(10) //推荐使用
合并set
val set3 = set1 ++ set2
set1 ++= set2 //set1合并set2,set1变,set2不变
Map集合
Scala中的Map和Java类似,也是一个散列表,它储存的内容是键值对(Key-Value),也称映射
不可变Map
创建Map
val map1: Map[String,Int] = Map("a" -> 13,"b" -> 23)
中括号里面是Key和Value的数据类型,小括号内是具体数据
遍历元素
map1.foreach(println) //foreach方法循环
取Map中所有的Key或者Value
for(key <- map1.keys){
println(s"$key --> ${map1.get(key)}")
访问某一个key的value
println(map1.get("a").get) //后面加一个 . get,但这个不安全
println(map1.get("c").get) //Key没有c,程序就会报错
println(map1.getOrElse("c",0) //map1中Key没有c,会打印出来0
println(map1("a")) //简便的方法,打印出来单有value
可变的Map集合
创建Map
val map1:mutable.Map[String,Int]=mutable.Map("a" -> 13,"b" -> 19)
mutable是分别可变与不可变Map的关键
添加元素
map1.put("c",6)
删除元素
map1.remove("a") //删除不需要键值对,用Key即可
修改元素
map1.update("a",45) //有Key是修改,没有Key是添加
合并两个Map
map1 ++=map2 //map1改变,map2不变,map2可以是不可变Map
val map3:Map[String,Int] = map2 ++map1 //map2是不可变map
元组
元组可以理解为一个容器,可以存放各种相同或者不同类型的数据。就是将多个无关的数据封装为一个整体,称为元组。元组最多有22个元素。
创建元组
val tuple1: (String,Int,Char,Boolean) = ("hello",100,'h',true)
前一个括号内是数据类型,后一个括号是数据,有几个数据,称为几元组
访问元素
println(tuple1._1) //1是第几个,位置为0
println(tuple1._3) //3是第几个,位置为2
println(tuple1.productElement(2)) //2是位置
遍历元组数据
for (elem <- tuple1.productIterator)
println(elem)
嵌套元组
val multuple = (12,0.4,"hello",(23,"hhh"),89) //元组内装元组
println(multuple._4._1) //一个是内元组的位置,第二个是内元组里面的位置
集合的基本属性和常用操作
获取长度——length
获取大小——size
循环遍历——foreach
迭代器——iterator
生成字符串——skString
是否包含——contains
衍生集合
val list1 = List(1,3,4,5,7)
val list2 = List(3,5,8,9,10)
获取集合的头
println(list1.head) //第一个元素,以集合形式取出
获取集合的尾(去除第一个元素都是尾)
println(list1.head) //除去头都是尾,以集合形式取出
获取集合的最后一个元素
println(list1.last)
获取集合初始数据(不是最后一个,都是初始元素)
println(list1.init)
反转(数据位置反转)
println(list1.reverse)
获取前(后)几个元素
println(list2.take(3)) //前,正数
println(list2.takeRight(4)) //后,倒数
去掉前(后)几个元素
println(list2.drop(3)) //前,正数
println(list2.dropRight(4)) //后,倒数
并集(set做并集,会去重)
val list3 = list1.union(list2) //叠加
list1 :::list2
交集
val list4 = list1.intersect(list2)
差集
val list5 = list1.diff(list2) //属于list1但不属于list2的数值
拉链(两个集合类型从第一个一一配对,组成二元组,多的去除)
println(list1.zip(list2)) //出来为list(1,2),(3,4),(4,6),谁在前,二元组中就在前
滑窗(又称滚动窗口)
list1.sliding(3) //在集合里面取三个数据,依次隔一个向下取
list1.sliding(4 ,2) //取四个数据,依次隔两个向下进行
集合计算简单函数
val list1 = List(2,4,1,-4,56)
求和(sum)
println(list1.sum)
求乘积(product)
println(list1.product)
最大值(max)当比较是二元组时,需要用maxBy方法
println(list1.max)
最小值(min)当比较是二元组时,需要用minBy方法
println(list1.min)
排序
sorted(从小到大)
println(list1.sorted)
传入隐式参数
println(list1.sorted(Ordering[Int].reverse))
sortBy(可以排序二元组)
println(list1.sortBy ( _._2 ) ) //安照元组第二个数值进行排序(化简后)
sortWith(小于号从小到大,大于号,从大到小)
println(list1.sortWith( (a:Int,b:Int) =>{a<b} ))
println(list1.sortWith(_<_) ) //化简后
高级操作
分割列表中的字符串(split())
val list2=list1.map(_.split(" ")) //按照空格进行分割
过滤
过滤偶数
val list2 = list1.filter( (elem:Int)=>{elem % 2 == 0} ) //0为偶,1为奇
val list3 = list1.filter(_ % 2 ==1) //过滤奇数,并化简
转化/映射(map)
把集合中的每个数乘2
println(list1.map(_ * 2)) //化简
扁平化(flatten)
val list4:List[List[Int]]=List(List(1,2,3),List(4,5,6),List(7,8,9))
val list5 = list4.flatten //flatten方法
扁平化+映射
val list6:List[String]=List("hello world","hello scala","we study")
需求:将List(字符串)里面的字符串数据分开,并保存在一个列表里面。
val list7=list6.flatMap(_.split(" ")) //打印为:List(hello, world, hello, scala, we, study)
分组(group,按照制定的规则对集合的元素进行分组,分组后为map)
简化(规约)
val list7 = List(1,2,3,4,5,6,7,8,9)
val list9 = List("hql","ms","hd","zmy","xsl")
分成奇偶两组
val list8:Map[Int,List[Int]]=list7.groupBy( _%2 )
打印出来为:
Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
给定一组词汇,按照单词的首字母进行分组
println( list9.groupBy( _.charAt(0) ) )
打印出来为:
Map(z -> List(zmy), h -> List(hql, hd), m -> List(ms), x -> List(xsl))
reduce
val list10 = List(3,4,5,8,10)
println(list10.reduce(_+_)) //从左到右依次减,结果为-24
println(list10.reduceLeft(_-_)) //与第上方一样
println(list10.reduceRight(_-_)) //从右面开始减,为6
//详细计算为 3-( 4-( 5-( 8-10 ) ) ) = 6
折叠
val list1 = List(1,2,3,4,10)
fold(与reduce相似)
println(list1.fold(10)(_+_)) //10 + 1 + 2 + 3 + 4
println(list1.foldRight(10)(_-_)) //10 - 1 - 2 - 3 - 4
println(list1.foldRight(11)(_-_)) //1-(2-(3-(4-(10-11))))
// 11是加上去的,在式子最右边
队列
Scala也提供了队列(Queue)的数据结构,队列的特点就是先进先出,进队和出队的方法分别是enqueue和dequeue。
创建可变队列
val queue = new mutable.Queue[String]()
入队操作
queue.enqueue("a","b","c")
出队操作
println(queue.dequeue()) //安照入队顺序,依次出队,一次一个
创建不可变队列
val queue2 = Queue (11,23,34,45) //需要导包
import scala.collection.mutable.Queue
添加元素
val queue3 = queue2.enqueue(45)
并行集合
Scala为了充分使用多核CPU,提供了并行集合(有利于前面的串行集合),用于多核环境的并行计算。