一、元组
object TupleDemo5 {
def main(args: Array[String]): Unit = {
/**
* 元组:固定长度的集合
* 元组和其他List,Set集合不太一样的地方是,元组的每一个元素数据类型,都可以是不一样的
*/
//5元组
val tuple5: (Int, Double, String, Boolean, Char) = Tuple5(1, 3.14, "string", true, 'c')
println(tuple5) //(1,3.14,string,true,c)
//使用“_加位置坐标(_1)”获取元组中的元素
println(tuple5._2) //3.14
}
}
二、集合
集合的分类
不可变集合:
List:有序,元素可重复,不可变,长度是固定的
Set:无序,且元素唯一
Map:元素是键值对格式存储的,键是唯一的
可变集合:
ListBuffer:操作是在原有的集合上进行改变
HashSet::同上
1、List
object JiHeDemo1 {
def main(args: Array[String]): Unit = {
//创建一个List集合对象
val intList: List[Int] = List(33, 22, 33, 44, 55, 66, 33, 77, 99, 11)
//获取集合长度
println(intList.size) //10
println(intList.length) //10
/**
* 提供了许多java集合没有的方法
*/
//通过下标所以获取元素
println(intList(1))
//获取第一个元素
println(intList.head)
//获取最后一个元素
println(intList.last)
//除去第一个元素外,返回一个新集合存储剩下的元素
val tailList: List[Int] = intList.tail
println(intList)
println(tailList) //List(22, 33, 44, 55, 66, 33, 77, 99, 11)
//使用分隔符拼接集合中的元素
val str: String = intList.mkString("|")
println(str)
//将集合元素反转,返回新的集合存储
val reverseList: List[Int] = intList.reverse
println(reverseList) //List(11, 99, 77, 33, 66, 55, 44, 33, 22, 33)
//从左向右取n个元素,返回一个新的集合存储
val leftToRight: List[Int] = intList.take(3)
println(leftToRight) //List(33, 22, 33)
//从右向左取n个元素,返回一个新的集合存储
val rightToLeft: List[Int] = intList.takeRight(4)
println(rightToLeft) //List(33, 77, 99, 11)
//从第一个元素开始取,直到函数的返回值是false的时候
//def takeWhile(p: A => Boolean)
val resList: List[Int] = intList.takeWhile(_ % 3 == 0)
println(resList) //List(33)
//去重集合中的元素,返回一个新的集合存储
val distinctLIst: List[Int] = intList.distinct
println(distinctLIst) //List(33, 22, 44, 55, 66, 77, 99, 11)
//针对元素是Int的List,可以使用sun函数求和
val sumList: Int = intList.sum
println(sumList) // 473
//获取集合中元素的最大值和最小值
println(intList.max)
println(intList.min)
//集合的遍历
//方式1:
for (e <- intList) {
println(e)
}
//方式2:
intList.foreach(println) // 等价于intLIst.foreach(println(_)) 等价于 intLIst.foreach(e=> println(e))
}
}
2、Set
/**
* Set集合:元素无需且唯一
* 除了排序以外,List集合有的函数,Set集合都有
*/
object JiHeDemo3 {
def main(args: Array[String]): Unit = {
//创建一个Set集合
val set1: Set[Int] = Set(11, 22, 33, 44, 55, 11, 22, 33, 44, 55)
println(set1) //Set(33, 22, 44, 11, 55)
println(set1.mkString("|")) //33|22|44|11|55
val set2: Set[Int] = Set(11, 22, 33)
val set3: Set[Int] = Set(22, 33, 44)
//交集
println(set2.&(set3)) //等价于println(set2 & set3) //Set(22, 33)
println(set2.intersect(set3)) //等价于println(set2 intersect set3)
//并集
println(set2.|(set3)) //Set(11, 22, 33, 44)
println(set2 | set3)
//差集
println(set2.&~(set3)) //Set(11)
println(set2 &~ set3)
/**
* 集合之间的转换:
* toSet、toList、toMap
*/
//Set-->LIst
val list: List[Int] = set1.toList
println(s"list:${list}") //List(33, 22, 44, 11, 55)
//List-->Set
println(s"set:${list.toSet}") //Set(33, 22, 44, 11, 55)
val set4: Set[String] = Set("a", "b", "c")
// 使用map方法将Set中的每个元素转换为(key, value)对,然后使用toMap方法转换为Map
val map: Map[String, Boolean] = set4.map((key: String) => (key, true)).toMap
println(map) //Map(a -> true, b -> true, c -> true)
}
}
3、Map
import scala.collection.{immutable, mutable}
/**
* Map:元素是键值对的集合,不可变
*/
object JiHeDemo6 {
def main(args: Array[String]): Unit = {
//创建一个Map集合
val map1: Map[Int, String] = Map((1001, "张三"), (1002, "李四")) //方式1
val map2: Map[Int, String] = Map(1001 -> "张三", 1002 -> "李四", 1003 -> "王五") //方式2
println(map1) //Map(1001 -> 张三, 1002 -> 李四)
println(map2) //Map(1001 -> 张三, 1002 -> 李四, 1003 -> 王五)
//通过键获取值
println(map1(1001)) //张三
// println(map1(1007)) //找不到会报错:NoSuchElementException
//通过键获取值,如果找不到返回默认值
println(map1.getOrElse(1007, "未找到该值")) //未找到该值
val map3: Map[String, Int] = Map("1001" -> 19, "1002" -> 12, "1003" -> 17, "1004" -> 16)
//需求:将每一个学生的年龄加1
val map4: Map[String, Int] = map3.map((kv: (String, Int)) => {
//这里的每个键值对,在map中被封装成一个2元组(key,value)
println(kv)
val key: String = kv._1
val value: Int = kv._2
key -> (value + 1) //等价于(key,value+1)
})
println(map4) //Map(1001 -> 20, 1002 -> 13, 1003 -> 18, 1004 -> 17)
//获取Map集合所有的键或所有值
val keys: Iterable[String] = map4.keys
println(keys) //Set(1001, 1002, 1003, 1004)
val values: Iterable[Int] = map4.values
println(values) //MapLike(20, 13, 18, 17)
/**
* 可变的map集合:HashMap
*/
val hashMap: mutable.HashMap[String, Int] = new mutable.HashMap[String, Int]()
//使用put添加元素
hashMap.put("张三", 19)
hashMap put ("李四", 17)
hashMap += "王五"->21
hashMap.+=(("赵六", 18))
println(hashMap) //Map(赵六 -> 18, 王五 -> 21, 张三 -> 19, 李四 -> 17)
//删除元素
hashMap.-=("赵六")
hashMap -= "王五"
println(hashMap) //Map(张三 -> 19, 李四 -> 17)
}
}
4、不可变集合ListBuffer与HashSet
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
/**
* 可变集合
* 通过观察源码发现,不可变集合属于scala.collection.immutable中
* 如果我们想要使用可变的集合,就要去scala.collection.mutable下找对应的集合进行使用
*
* ListBuffer 操作是在原有的集合上进行改变
*/
object JiHeDemo4 {
def main(args: Array[String]): Unit = {
val listBuffer1: ListBuffer[String] = new ListBuffer[String]
//添加元素
listBuffer1.append("hao")
listBuffer1 append "hao"
listBuffer1.+=("xue")
listBuffer1 += "xi"
println(listBuffer1) //ListBuffer(hao, hao, xue, xi)
//删除元素,从左向右,只会删除第一次出现的对应字符串
listBuffer1.-=("hao")
println(listBuffer1) //ListBuffer(hao, xue, xi)
//同过下标索引删除元素,返回被删除的元素
val str: String = listBuffer1.remove(1)
println(str) //xue
println(listBuffer1) //ListBuffer(hao, xi)
//批量添加元素
val listBuffer2: ListBuffer[String] = ListBuffer("aaa", "bbb", "ccc")
listBuffer1.++=(listBuffer2)
println(listBuffer1) //ListBuffer(hao, xi, aaa, bbb, ccc)
println(listBuffer2) //ListBuffer(aaa, bbb, ccc)
//更新(修改)元素
listBuffer2.update(2, "ddd")
println(listBuffer2) //ListBuffer(aaa, bbb, ddd)
//指定索引位置插入元素
listBuffer2.insert(2, "ccc")
println(listBuffer2) //ListBuffer(aaa, bbb, ccc, ddd)
/**
* 可变Set集合:HashSet
* HashSet中的操作与ListBuffer基本一致,在此不作赘述
*
*/
val hashSet = new mutable.HashSet[Int]()
hashSet.+=(11)
hashSet.+=(22)
println(hashSet) //Set(22, 11)
}
}
5、scala集合与java互相转换
import java.util
import scala.collection.JavaConverters.{asScalaBufferConverter, seqAsJavaListConverter}
/**
* scala中的集合与Java中的集合互相转换
*/
object JiHeDemo10 {
def main(args: Array[String]): Unit = {
//创建一个java中的集合
val arrayList: util.ArrayList[String] = new util.ArrayList[String]()
arrayList.add("java")
arrayList.add("python")
arrayList.add("scala")
arrayList.add("spark")
/**
* java集合-->scala集合
* 借助隐式转换,调用原本没有的功能
*/
val list: List[String] = arrayList.asScala.toList
println(list.sortBy((e:String)=>e)) //List(java, python, scala, spark)
/**
* scala集合-->java集合
*/
val list1: List[Int] = List[Int](11, 22, 33, 44, 55)
val javaLisrt: util.List[Int] = list1.asJava
println(javaLisrt)
}
}
三、高阶函数
高阶函数:高阶函数(Higher-Order Functions)指的是那些接受函数作为参数或者返回函数作为结果的函数
高阶函数都是操作 Scala 集合的,一般会进行两类操作:转换操作(transformation )和行动操作/聚合操作(actions)。第一种操作类型将集合转换为另一个集合,第二种操作类型返回某些类型的值。
以下是常用的高阶函数:
1、遍历( foreach ):处理集合中每一个元素,直接输出或者其他处理,没有返回值的,不会返回新的集合
2、映射( map ): 处理集合中每一个元素,有返回值的,将处理后的结果使用新的集合存储
3、嵌套的结构展开(flatten):flatten可以把嵌套的结构展开。当有一个集合的集合,然后你想对这些集合的所有元素进行操作时,就会用到 flatten。
4、映射扁平化( flatmap ):flatMap结合了map和flatten的功能。接收一个可以处理嵌套列表的函数,然后把返回结果连接起来。可以把 flatMap,理解为先map,然后再flatten
5、过滤( filter ):过滤出符合条件的元素,有返回值的
6、是否存在( exists )
7、排序( sorted 、 sortBy 、 sortWith )
8、分组( groupBy )
9、聚合计算( reduce )
10、折叠( fold )
object JiHeDemo2 {
def main(args: Array[String]): Unit = {
val intList: List[Int] = List(33, 22, 33, 44, 55, 66, 33, 77, 99, 11)
/**
* 1、foreach: 处理集合中每一个元素,直接输出或者其他处理,没有返回值的,不会返回新的集合
*/
//需求:对集合的偶数元素求和
var sum = 0
intList.foreach((e: Int) => {
if (e % 2 == 0) {
sum += e
}
})
println(f"集合的偶数元素和为${sum}")
/**
* 2、map: 处理集合中每一个元素,有返回值,将处理后的结果使用新的集合存储
*/
//需求:将集合中元素偶数+50,基奇数+100
val intListMap: List[Int] = intList.map((e: Int) => {
if (e % 2 == 0) {
e + 50
} else {
e + 100
}
})
println(intList) //List(33, 22, 33, 44, 55, 66, 33, 77, 99, 11)
println(intListMap) //List(133, 72, 133, 94, 155, 116, 133, 177, 199, 111)
/**
* 3、filter:循环集合,将集合中的每一个元素传入到后面的函数中,如果函数的结果为true,
* 那么这个元素就会被添加到新的集合中,否则不添加
* 新集合的结果就是过滤后的结果
*/
//需求:过滤出集合中的偶数元素
val intLIstFilter: List[Int] = intList.filter((e: Int) => {
e % 2 == 0
})
println(intLIstFilter) //List(22, 44, 66)
/**
* 4、flatten:把嵌套的结构展开。当有一个集合的集合,然后你想对这些集合的所有元素进行操作时,就会用到 flatten。
*/
val arr1: Array[Int] = Array[Int](11, 22, 33)
val arr2: Array[Int] = Array[Int](44, 55, 66)
val arrList: List[Array[Int]] = List(arr1, arr2)
println(arrList.flatten) //List(11, 22, 33, 44, 55, 66)
/**
* 5、flatMap:效果类似于hive中的explode函数
* flatMap的工作方式是将集合中的每个元素应用一个函数,每个元素经过该函数会返回一个新的集合,
* 然后将所有这些新集合的元素“扁平化”到一个单一的集合中
*/
val stringList1: List[String] = List("python|java|scala", "mysql|clickhouse|hbase", "hadoop|hive|zookeeper")
//需求:将每一个单词切分出来
//方式一:for循环
for (words <- stringList1) {
val stringsArr: Array[String] = words.split("\\|")
for (word <- stringsArr) {
println(word)
}
}
println("-" * 100)
//方式2:flatMap
val stringList2: List[String] = stringList1.flatMap((words: String) => {
val stringsLIst: Array[String] = words.split("\\|")
stringsLIst
})
println(stringList2) //List(python, java, scala, mysql, clickhouse, hbase, hadoop, hive, zookeeper)
println("-" * 100)
/**
* 6、sort by:排序
* 将集合中的每一个元素传入到后面的函数中,以指定的方式进行排序
*/
val listSort1: List[Int] = intList.sortBy((e: Int) => e) //默认以从小到大的顺序排序
println(listSort1) //List(11, 22, 33, 33, 33, 44, 55, 66, 77, 99)
val listSort2: List[Int] = intList.sortBy((e: Int) => -e) //加"-"表示以从大到小的顺序排序
println(listSort2) //List(99, 77, 66, 55, 44, 33, 33, 33, 22, 11)
//sortWith:指定排序方式
val listSort3: List[Int] = intList.sortWith((x: Int, y: Int) => x > y)
println(listSort3) //List(99, 77, 66, 55, 44, 33, 33, 33, 22, 11)
/**
* 7、groupBy: 分组
* 将集合中的每一个元素传入到后面的函数中,相同的元素为一组,返回的是一个Map集合
*/
val intListGroupBy: Map[Int, List[Int]] = intList.groupBy((e: Int) => e)
println(intListGroupBy) //Map(33 -> List(33, 33, 33), 77 -> List(77), 22 -> List(22), 44 -> List(44), 66 -> List(66), 11 -> List(11), 99 -> List(99), 55 -> List(55))
}
}
四、入门案例练习(单词统计)
import scala.io.{BufferedSource, Source}
/**
* 使用scala语言完成单词统计
*/
object worldCountDemo7 {
def main(args: Array[String]): Unit = {
//方式一:分开调用
val source: BufferedSource = Source.fromFile("D:\\projects\\IdeaProjects\\bigdata29-maven\\scala\\src\\main\\scala\\com\\shujia\\day01\\data\\she_hui_zhu_yi_new")
val list: List[String] = source.getLines().toList
println(list) //List(富强、民主、文明, 富强、民主、文明、和谐, 富强、民主、文明、和谐, 爱国、敬业、友善, 爱国、敬业、诚信、友善, 爱国、敬业、诚信、友善)
val wordList: List[String] = list.flatMap(e => e.split("、"))
println(wordList) //List(富强, 民主, 文明, 富强, 民主, 文明, 和谐, 富强, 民主, 文明, 和谐, 爱国, 敬业, 友善, 爱国, 敬业, 诚信, 友善, 爱国, 敬业, 诚信, 友善)
val mapWord: Map[String, List[String]] = wordList.groupBy(e => e)
println(mapWord) //Map(诚信 -> List(诚信, 诚信), 富强 -> List(富强, 富强, 富强), 爱国 -> List(爱国, 爱国, 爱国), 敬业 -> List(敬业, 敬业, 敬业), 文明 -> List(文明, 文明, 文明), 友善 -> List(友善, 友善, 友善), 民主 -> List(民主, 民主, 民主), 和谐 -> List(和谐, 和谐))
val mapCount: Map[String, Int] = mapWord.map((kv: (String, List[String])) => {
kv._1 -> kv._2.size
// s"${kv._1}:${kv._2.size}"
})
mapCount.foreach(println)
println("=" * 100)
//方式二:链式调用
Source.fromFile("scala/data/she_hui_zhu_yi")
.getLines()
.toList
.flatMap(e => e.split("、"))
.groupBy(e => e)
.map((kv: (String, List[String])) => kv._1 -> kv._2.size)
.foreach(println)
}
}