Scala06 数据结构
6.1 数组
存储数据类型相同的元素
6.1.1 数组定义
6.1.1 不可变数组
格式:
val arr=new Array[T](数组长度)
- [T] : 是指顶数组所存放数组的类型,T表示泛型,如果希望存放任意数据类型,则指定Any。
案例:
// 创建不可变数组
val array = new Array[Int](10)
// 也可以使用伴生对象的apply方法
val array1: Array[Int] = Array(1, 2, 3, 4)
// 遍历读取array
println(array)
for (elem <- array1) {
println(elem)
}
// 使用迭代器遍历数组
val iterator: Iterator[Int] = array1.iterator
while (iterator.hasNext) {
val i: Int = iterator.next()
println(i)
}
println("===========================")
// scala函数式编程的写法
def myPrint(i: Int): Unit = {
println(i)
}
// 放入自定义出来的函数
array1.foreach(myPrint)
// 直接使用匿名函数
array1.foreach(i => println(i * 2))
// 最简单的打印形式 直接使用系统的函数
array1.foreach(println)
// 修改数组的元素
println(array1(0))
array1(0) = 10
println(array1(0))
// 添加元素
// array1保持不变
val array2: Array[Int] = array1 :+ 1
6.1.2 可变数组
格式:
val arr=ArrayBuffer[T]()
- 使用ArrayBuffer需要引入scala.collection.mutable.ArrayBuffer
案例:
// 可变数组
// 默认使用的集合都是不可变的
// 使用可变集合 需要自己提前导包
val arrayBuffer: ArrayBuffer[Int] = new ArrayBuffer[Int]()
val arrayBuffer1: ArrayBuffer[Int] = ArrayBuffer(1, 2, 3, 4)
// 向可变数组中添加元素
arrayBuffer.append(10)
arrayBuffer1.appendAll(Array(1, 2, 3, 4))
// 遍历打印
arrayBuffer.foreach(println)
arrayBuffer1.foreach(println)
println(arrayBuffer1)
// 修改元素
arrayBuffer1.update(0, 100)
arrayBuffer1(1) = 200
println(arrayBuffer1)
// 查看元素
println(arrayBuffer1(0))
// 删除元素
arrayBuffer1.remove(0)
println(arrayBuffer1)
arrayBuffer1.remove(1, 3)
println(arrayBuffer1)
6.1.3 数组的转换
格式:
arr.toBuffer //不可变数组转可变数组
arr.toArray //可变数组转不可变数组
案例:
// 可变数组和不可变数组的转换和关系
// 不可变
val ints: Array[Int] = Array(1, 2, 3, 4)
// 可变
val ints1: ArrayBuffer[Int] = ArrayBuffer(5, 6, 7, 8)
// 不可变的用符号
val b: Array[Int] = ints :+ 1
ints.foreach(println)
b.foreach(println)
// 可变的用方法
ints1.append(1)
println(ints1)
val ints2: ArrayBuffer[Int] = ints1 :+ 2
println(ints1)
// 可变数组转换为不可变数组
val array: Array[Int] = ints1.toArray
// array.append
// 不可变数组转可变数组
// 结果用多态表示
val buffer: mutable.Buffer[Int] = ints.toBuffer
val buffer1: ArrayBuffer[Int] = buffer.asInstanceOf[ArrayBuffer[Int]]
buffer.append(1)
6.1.4 多维数组
格式:
val arr = Array.ofDim[T]()
案例:
定义一个二维数组,里面有三个一维数组,每个一维数组中有四个元素
// 多维数组
val arrayDim = new Array[Array[Int]](3)
arrayDim(0) = Array(1, 2, 3, 4)
arrayDim(1) = Array(1, 2, 3, 4)
arrayDim(2) = Array(1, 2, 3, 4)
for (array <- arrayDim) {
for (elem <- array) {
print(elem + "\t")
}
println()
}
// scala中的方法
val arrayDim1: Array[Array[Int]] = Array.ofDim[Int](3, 4)
arrayDim1(0)(1) = 100
for (array <- arrayDim1) {
for (elem <- array) {
print(elem + "\t")
}
println()
}
6.2 元组
概念:
Scala的元组是对多个不同类型对象的一种简单封装,它将不同的值用小括号括起来,并用逗号作分隔,即表示元组。
格式:
val tuple=(元素1,元素2,...)
注意:元组中最大只能有22个元素
案例:
//(1)声明元组的方式:(元素1,元素2,元素3)
val tuple: (Int, String, Boolean) = (40, "bobo", true)
//(2)访问元组
//(2.1)通过元素的顺序进行访问,调用方式:_顺序号
println(tuple._1)
println(tuple._2)
println(tuple._3)
//(2.2)通过索引访问数据
println(tuple.productElement(0))
//(2.3)通过迭代器访问数据
for (elem <- tuple.productIterator) {
println(elem)
}
//(3)Map中的键值对其实就是元组,只不过元组的元素个数为2,称之为对偶
val map = Map("a" -> 1, "b" -> 2, "c" -> 3)
val map1 = Map(("a", 1), ("b", 2), ("c", 3))
map.foreach(tuple => {
println(tuple._1 + "=" + tuple._2)
})
6.3 集合
概述:
- Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。
- 几乎所有的集合类,Scala都同时提供了可变和不可变的版本,分别位于以下两个包。
- 不可变集合:scala.collection.immutable
- 可变集合: scala.collection.mutable
- Scala不可变集合,就是指该集合对象不可修改,每次修改就会返回一个新对象,而不会对原对象进行修改。类似于java中的String对象。
- 可变集合,就是这个集合可以直接对原对象进行修改,而不会返回新的对象。类似于java中StringBuilder对象。
6.3.1 List 集合
在Scala中,List列表和数组类似,列表的所有元素都具有相同类型。然而,列表与数组不同的是,列表是不可变的(即列表的元素不能通过赋值来更改)。
格式:
val 变量名:List[数据类型]=List(数据)
案例:
// 字符串
val fruit: List[String] = List("apples", "oranges", "pears")
// 整型
val nums: List[Int] = List(1, 2, 3, 4)
// 空
val empty: List[Nothing] = List()
// 二维列表
val dim: List[List[Int]] =
List(
List(1, 0, 0),
List(0, 1, 0),
List(0, 0, 1)
)
在Scala中,可以使用“Nil”和“::”操作符来定义列表。其中,“Nil”表示空列表;“::”意为构造,向列表的头部追加数据,创造新列表。
案例:
// 字符串
val fruit = "apples":: ("oranges"::("pears"::Nil))
// 整型
val nums = 1::(2::(3::(4::Nil)))
// 空列表
val empty = Nil
// 二维列表
val dim = (1::(0::(0::Nil))) ::
(0::(1::(0::Nil))) ::
(0::(0::(1::Nil)))::Nil
表1 Scala中操作List的常见方法
方法名称 | 相关说明 |
---|---|
head | 获取列表第一个元素 |
tail | 返回除第一个之外的所有元素组成的列表 |
isEmpty | 若列表为空,则返回true,否则返回false |
take | 获取列表前n个元素 |
contains | 判断是否包含指定元素 |
想要学习更多操作List的方法,请参考
https://www.scala-lang.org/api/current/scala/collection/immutable/List.html
进行学习
// 字符串列表
object Test {
def main(args: Array[String]) {
val site = "Runoob" :: ("Google" :: ("Baidu" :: Nil))
val nums = Nil
println( "第一网站是 : " + site.head )
println( "最后一个网站是 : " + site.tail )
println( "查看列表 site 是否为空 : " + site.isEmpty )
println( "查看 nums 是否为空 : " + nums.isEmpty )
}
}
6.3.2 Set 集合
- Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。
- Scala 集合分为可变的和不可变的集合。
- 默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
格式:
val 变量名:Set[集合类型]=Set(数据)
案例1:不可变集合
// (1) 创建set 使用伴生对象的apply方法
val set: Set[Int] = Set(4, 3, 2, 1)
val set1 = Set(1, 2, 3, 4, 2, 8, 4, 3, 7)
// (2) set的特点 无序不可重复
println(set)
// (3) 默认使用hash set
// 如果元素少于等于4个 会创建特定类型的set
println(set.isInstanceOf[HashSet[Int]])
val hashSet: HashSet[Int] = HashSet(1, 2, 3, 4, 5)
// 不可变使用符号
val set2: Set[Int] = set + 1
println(set2)
// 作用 判断集合是否包含某个元素
val bool: Boolean = set.contains(2)
案例2:可变集合( scala.collection.mutable.Set)
// (1)可变的set
val set3: mutable.Set[Int] = mutable.Set(1, 2, 3, 4, 4, 3, 2, 1)
// 同样数据不可重复且无序
println(set3)
// (2) 添加元素
// 会使用返回值来告诉你有没有加入进去
val bool1: Boolean = set3.add(5)
println(set3)
// 遍历查询set
set3.foreach(println)
// (3)删除元素 填写的不是下标是删除的元素
val bool2: Boolean = set3.remove(3)
println(set3)
表2 Scala中操作Set集合的常见方法
方法名称 | 相关说明 |
---|---|
head | 获取Set集合的第一个元素 |
tail | 返回除第一个之外的所有元素组成的Set集合 |
isEmpty | 若Set集合为空,则返回true,否则返回false |
take | 获取Set集合前n个元素 |
contains | 判断Set集合是否包含指定元素 |
想要学习更多操作Set集合的方法,请参考
https://www.scala-lang.org/api/current/scala/collection/Set.html
进行学习。
案例2:常见操作
val site = Set("bilibili", "Google", "Baidu")
val nums: Set[Int] = Set()
println("第一网站是 : " + site.head)
println("最后一个网站是 : " + site.tail)
println("查看集合 site 是否为空 : " + site.isEmpty)
println("查看 nums 是否为空 : " + nums.isEmpty)
println("查看site 的前两个网站: " + site.take(2))
println("查看集合是否包含网站Google: " + site.contains("Google"))
6.3.3 Map 集合
- 在Scala中,Map是一种可迭代的键值对(key/value)结构,并且键是唯一的,值不一定是唯一的,所有的值都是通过键来获取的。
- Map中所有元素的键与值都存在一种对应关系,这种关系即为映射。
- Map有两种类型,可变与不可变,区别在于可变对象可修改,而不可变对象不可修改。
- 在 Scala 中,可以同时使用可变与不可变 Map ,默认使用不可变Map。
- 若需要使用可变的Map集合,则需要引入
import scala.collection.mutable.Map
类。
格式:
val 集合名:Map[key 类型,value 类型] = Map(key -> value, key -> value,......)
案例:
val colors = Map("red" -> "#FF0000", "azure" -> "#F0FFFF")
常见方法:
表3 Scala中操作Map集合的常见方法
方法名称 | 相关说明 |
---|---|
() | 根据某个键查找对应的值,类似于Java中的get() |
contains() | 检查Map中是否包含某个指定的键 |
getOrElse() | 判断是否包含键,若包含返回对应的值,否则返回其他的 |
keys | 返回Map所有的键(key) |
values | 返回Map所有的值(value) |
isEmpty | 若Map为空时,返回true |
想要学习更多操作Map集合的方法,请参考
https://www.scala-lang.org/api/current/scala/collection/immutable/Map.html
进行学习。
案例:
val colors = Map("red" -> "#FF0000",
"azure" -> "#F0FFFF",
"peru" -> "#CD853F")
val peruColors = if (colors.contains("peru")) colors("peru") else 0
val azureColor = colors.getOrElse("azure", 0)
println("获取colors中键为red的值:" + colors("red"))
println("获取colors 中所有的键 : " + colors.keys)
println("获取colors 中所有的值 : " + colors.values)
println("检测 colors 是否为空 : " + colors.isEmpty)
println("判断colors是否包含键peru包含则返回对应值,否则返回0:" + peruColors)
println("判断colors是否包含键azure,包含则获取对应值,否则返回0:" + azureColor)
6.4 数据结构常用方法
6.4.1 基本属性和常用操作
- 获取长度
- 获取大小
- 循环遍历
- 迭代器
- 生成字符串
- 是否包含
案例:
val list: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
//(1)获取集合长度
println(list.length)
//(2)获取集合大小,等同于length
println(list.size)
//(3)循环遍历
list.foreach(println)
//(4)迭代器
for (elem <- list.itera tor) {
println(elem)
}
//(5)生成字符串
println(list.mkString(","))
//(6)是否包含
println(list.contains(3))
6.4.2 衍生集合
- 获取头
- 获取尾(不是头的就是尾)
- 最后一个数据
- 初始数据(不包含最后一个)
- 反转
- 取前(后)n个元素
- 去掉前(后)n个元素
- 并集
- 交集
- 差集
- 拉链
- 滑窗
案例:
val list1: List[Int] = List(1, 2, 3, 4, 5, 6, 7)
val list2: List[Int] = List(4, 5, 6, 7, 8, 9, 10)
//(1)获取头
println(list1.head)
//(2)获取尾(不是头的就是尾)
println(list1.tail)
//(3)最后一个数据
println(list1.last)
//(4)集合初始数据(不包含最后一个)
println(list1.init)
//(5)反转
println(list1.reverse)
//(6)取前(后)n个元素
println(list1.take(3))
println(list1.takeRight(3))
//(7)去掉前(后)n个元素
println(list1.drop(3))
println(list1.dropRight(3))
//(8)并集
println(list1.union(list2))
//(9)交集
println(list1.intersect(list2))
//(10)差集
println(list1.diff(list2))
//(11)拉链 注:如果两个集合的元素个数不相等,那么会将同等数量的数据进行拉链,多余的数据省略不用
println(list1.zip(list2))
//(12)滑窗
list1.sliding(2, 5).foreach(println)
6.4.3 计算初级函数
- 求和
- 求乘积
- 最大值
- 最小值
- 排序
案例:
val list: List[Int] = List(1, 5, -3, 4, 2, -7, 6)
val list1: ListBuffer[Int] = ListBuffer(1, 5, -3, 4, 2, -7, 6)
// (1)求和
val sum: Int = list.sum
println(sum)
// (2)求乘积
val product: Int = list.product
println(product)
// (3)最大值
val max: Int = list.max
// (4)最小值
val min: Int = list.min
// (5)排序
val sorted: List[Int] = list.sorted
println(list)
println(sorted)
// 修改排序规则 从大到小
val ints: List[Int] = list.sorted(Ordering[Int].reverse)
println(ints)
// 对元组进行排序
val tuples = List(("hello", 10), ("world", 2), ("scala", 9), ("haha", 4),("hello", 1))
// 按照元组的默认字典序排列
val sorted1: List[(String, Int)] = tuples.sorted
println(sorted1)
// 按照后面数字从小到大排序
val tuples1: List[(String, Int)] = tuples.sortBy((tuple: (String, Int)) => tuple._2)
println(tuples1)
// 按照后面数字从大到小排序
val tuples2: List[(String, Int)] = tuples.sortBy((tuple: (String, Int)) => tuple._2)(Ordering[Int].reverse)
println(tuples2)
tuples.sortBy( _._2 )
// 自定义排序规则
val tuples3: List[(String, Int)] = tuples.sortWith((left: (String, Int), right: (String, Int)) => left._2 > right._2)
println(tuples3)
val tuples4: List[(String, Int)] = tuples.sortWith(_._2 > _._2)
println(tuples4)
- sorted : 对一个集合进行自然排序,通过传递隐式的Ordering。
- sortBy : 对一个属性或多个属性进行排序,通过它的类型。
- sortWith : 基于函数的排序,通过一个comparator函数,实现自定义排序的逻辑。
6.4.4 综合案例:单词统计
将集合中出现的相同的单词,进行计数,取计数排名前三的结果。
// 单词计数:将集合中出现的相同的单词,进行计数,取计数排名前三的结果
val stringList = List("Hello Scala Hbase kafka", "Hello Scala Hbase", "Hello Scala", "Hello")
// (1)将每一个字符串转换成一个一个单词
val wordList: List[String] = stringList.flatMap(str => str.split(" "))
println(wordList)
// (2)将相同的单词放置在一起
val wordToWordsMap: Map[String, List[String]] = wordList.groupBy(word => word)
println(wordToWordsMap)
// (3)对相同的单词进行计数
// (word, list) => (word, count)
val wordToCountMap: Map[String, Int] = wordToWordsMap.map(tuple => (tuple._1, tuple._2.size))
println(wordToCountMap)
//(4)对计数完成后的结果进行排序(降序)
val sortList: List[(String, Int)] = wordToCountMap.toList.sortWith {
(left, right) => {
left._2 > right._2
}
}
println(sortList)
// (5)对排序后的结果取前3名
val resultList: List[(String, Int)] = sortList.take(3)
println(resultList)