1.常用函数:
object Test11_CommonOp {
def main(args: Array[String]): Unit = {
val list = List(1,3,5,7,2,89)
val set = Set(23,34,423,75)
// (1)获取集合长度
println(list.length)
// (2)获取集合大小
println(set.size)
// (3)循环遍历
for (elem <- list)
println(elem)
set.foreach(println)
// (4)迭代器
for (elem <- list.iterator) println(elem)
println("====================")
// (5)生成字符串
println(list)
println(set)
println(list.mkString("--"))
// (6)是否包含
println(list.contains(23))
println(set.contains(23))
}
}
object Test12_DerivedCollection {
def main(args: Array[String]): Unit = {
val list1 = List(1,3,5,7,2,89)
val list2 = List(3,7,2,45,4,8,19)
println("----------------------------")
println("list1: " + list1)
println("list2: " + list2)
// (1)获取集合的头
println("head: => "+ list1.head)
// (2)获取集合的尾(不是头的就是尾)
println("tail: => "+ list1.tail)
// (3)集合最后一个数据
println("last: => "+ list2.last)
// (4)集合初始数据(不包含最后一个)
println("init: => "+ list2.init)
// (5)反转
println("reverse: => "+ list1.reverse)
// (6)取前(后)n个元素
println("take:取前3个元素 => "+ list1.take(3))
println("take:取后4个元素 => "+ list1.takeRight(4))
// (7)去掉前(后)n个元素
println("drop: 去掉前3个元素 => "+ list1.drop(3))
println("dropRight: 去掉后4个元素 => "+ list1.dropRight(4))
println("=========================")
println("list1: " + list1)
println("list2: " + list2)
println("============ 并集 =============")
// (8)并集
val union = list1.union(list2)
println("两个List集合并集,union: => " + union)
//使用符号方法合并两个集合,三冒号:::
println(list1 ::: list2)
// 如果是set做并集,会去重
val set1 = Set(1,3,5,7,2,89)
val set2 = Set(3,7,2,45,4,8,19)
val union2 = set1.union(set2)
println("两个set集合的union: " + union2)
println("两个set集合,并集符号操作"+ set1 ++ set2)
println("-----------交集------------")
println("list1: " + list1)
println("list2: " + list2)
// (9)交集
val intersection = list1.intersect(list2)
println("交集intersection: " + intersection)
println("---------差集--------------")
println("list1: " + list1)
println("list2: " + list2)
// (10)差集,存在于一个集合,而不属于另一个集合的元素,例如:属于list1,而不属于list2的元素,叫list1对list2的差集
val diff1 = list1.diff(list2)
val diff2 = list2.diff(list1)
println("差集diff1: " + diff1)
println("差集diff2: " + diff2)
println("-----------拉链------------")
println("list1: " + list1)
println("list2: " + list2)
// (11)拉链
println("list1拉链list2, zip: " + list1.zip(list2))
println("list2拉链list1, 拉链zip: " + list2.zip(list1))
println("================ 滑窗 ==================")
println("list1: " + list1)
println("list2: " + list2)
/*
(12)滑窗,按照规定的窗口大小,滑动获取元素,比如3个元素大小的滑动窗口,依次获得取出元素进行操作,
滑动窗口获取的是一个迭代器集合.
例如: list1: List(1, 3, 5, 7, 2, 89)这个集合,滑动窗口为3,窗口步长为1:获取的集合分别为:
List(1, 3, 5)
List(3, 5, 7)
List(5, 7, 2)
List(7, 2, 89)
*/
println(list1.sliding(3))
println("----------遍历窗口大小为3的滑动窗口获取的元素:-------------")
for (elem <- list1.sliding(3))
println(elem)
println("-----------------------")
/*
* 这个集合list2: List(3, 7, 2, 45, 4, 8, 19),假设滑动窗口大小为4,步长为2,获取的集合分别为:
* List(3, 7, 2, 45)
List(2, 45, 4, 8)
List(4, 8, 19)
*/
println("---------- 遍历滑动窗口大小为4,步长为2的滑动窗口获取的集合分别为 -------------")
for (elem <- list2.sliding(4, 2))
println(elem)
println("---------- 遍历滑动窗口大小为3,步长为3的滑动窗口获取的集合分别为 -------------")
for (elem <- list2.sliding(3, 3))
println(elem)
}
}
----------------------------
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
head: => 1
tail: => List(3, 5, 7, 2, 89)
last: => 19
init: => List(3, 7, 2, 45, 4, 8)
reverse: => List(89, 2, 7, 5, 3, 1)
take:取前3个元素 => List(1, 3, 5)
take:取后4个元素 => List(5, 7, 2, 89)
drop: 去掉前3个元素 => List(7, 2, 89)
dropRight: 去掉后4个元素 => List(1, 3)
=========================
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
============ 并集 =============
两个List集合并集,union: => List(1, 3, 5, 7, 2, 89, 3, 7, 2, 45, 4, 8, 19)
List(1, 3, 5, 7, 2, 89, 3, 7, 2, 45, 4, 8, 19)
两个set集合的union: Set(5, 89, 1, 2, 45, 7, 3, 8, 19, 4)
两个set集合,并集符号操作 Set(5, 89, 1, 2, 45, 7, 3, 8, 19, 4)
-----------交集------------
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
交集intersection: List(3, 7, 2)
---------差集--------------
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
差集diff1: List(1, 5, 89)
差集diff2: List(45, 4, 8, 19)
-----------拉链------------
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
list1拉链list2, zip: List((1,3), (3,7), (5,2), (7,45), (2,4), (89,8))
list2拉链list1, 拉链zip: List((3,1), (7,3), (2,5), (45,7), (4,2), (8,89))
================ 滑窗 ==================
list1: List(1, 3, 5, 7, 2, 89)
list2: List(3, 7, 2, 45, 4, 8, 19)
<iterator>
----------遍历窗口大小为3的滑动窗口获取的元素:-------------
List(1, 3, 5)
List(3, 5, 7)
List(5, 7, 2)
List(7, 2, 89)
-----------------------
---------- 遍历滑动窗口大小为4,步长为2的滑动窗口获取的集合分别为 -------------
List(3, 7, 2, 45)
List(2, 45, 4, 8)
List(4, 8, 19)
---------- 遍历滑动窗口大小为3,步长为3的滑动窗口获取的集合分别为 -------------
List(3, 7, 2)
List(45, 4, 8)
List(19)
1.常见函数:
(1) 求和
(2) 求乘积
(3) 最大值
(4) 最小值
(5) 排序:
object Test13_SimpleFunction {
def main(args: Array[String]): Unit = {
val list = List(5,1,8,2,-3,4)
val list2 = List(("a", 5), ("b", 1), ("c", 8), ("d", 2), ("e", -3), ("f", 4))
// (1)求和
var sum = 0
for (elem <- list){
sum += elem
}
println("list集合求和" + sum)
println("list集合求和sum函数" + list.sum)
// (2)求乘积
println("list集合求乘积product函数" + list.product)
// (3)最大值
println("list集合求max最大值" + list.max)
/*
* list2集合:List(("a", 5), ("b", 1), ("c", 8), ("d", 2), ("e", -3), ("f", 4))
* 对于这种集合,集合内部是一些二元组,那么我们如何根据二元组的第二个数值进行判断取最大值呢?这就是需要使用MaxBy()函数了,
* MaxBy()函数需要传一个函数作为参数,所传的函数是对数据最大值判断逻辑
* 例如:list2.maxBy( (tuple: (String, Int)) => tuple._2 ),其中tuple._2表示取二元组的第二个元素进行判断
* 也可以简化成:list2.maxBy( _._2 ),当函数的参数类型一定的情况下,参数类型可以省略,函数体是对元组取第二个值,
* 可以使用_作为通配符表示元组对象本身,_2表示元组对象的第二个元素。
*/
println(list2.maxBy( (tuple: (String, Int)) => tuple._2 ))
println(list2.maxBy( _._2 ))
// (4)最小值
println("list集合求min最小值" + list.min)
//MinBy()函数传一个函数作为参数,用于定义最小值的判断规则
println(list2.minBy(_._2))
println("========================")
// (5)排序
// 5.1 sorted 默认从小到大排序
val sortedList = list.sorted //list是不可变List集合,我们把排序好的新集合赋值给一个值保存
println("list集合sorted排序: " + sortedList)
// 从大到小逆序排序
println("从大到小逆序排序: "+ list.sorted.reverse)
// 传入隐式参数,Ordering[Int],这个类型是排序类型Ordering[Int]
println(list.sorted(Ordering[Int].reverse))
println(list2.sorted)
// 5.2 sortBy, 这个函数可以传一个函数作为参数,用于指定排序的元素,比如指定为元组的第二个元素,_2
println(list2.sortBy(_._2))
//传入隐式参数,实现倒序排列
println(list2.sortBy(_._2)(Ordering[Int].reverse))
// 5.3 sortWith,这个函数需要传一个函数作为参数,函数定义的是比较规则,类似于Java的Compare方法
//下面这个是Lambad表达式,表示传入的函数为 :(a: Int, b: Int) => {a < b} 大括号里面是比较规则
println(list.sortWith( (a: Int, b: Int) => {a < b} ))
//由于参数a和b,以及函数体中参数均是出现一次,可以使用_通配符代替,下面为简化的写法:
println(list.sortWith( _ < _ ))
//这个是从大到小排序
println(list.sortWith( _ > _))
}
}
在 Scala 中,Ordering[Int]
是一个类型类(type class),用于指定整数类型的比较规则。它提供了对整数的比较操作,可以用于排序、查找最大值和最小值等操作。
在标准库中,Scala 已经为 Int
类型提供了默认的比较规则。因此,当你使用 Ordering[Int]
时,实际上使用的是默认的比较规则。
以下是使用 Ordering[Int]
的一些常见操作:
val a = 5
val b = 10
if (Ordering[Int].compare(a, b) < 0) {
println("a 小于 b")
} else if (Ordering[Int].compare(a, b) > 0) {
println("a 大于 b")
} else {
println("a 等于 b")
}
val numbers = List(5, 3, 1, 4, 2)
val sortedNumbers = numbers.sorted(Ordering[Int])
println(sortedNumbers) // 输出 List(1, 2, 3, 4, 5)
val numbers = List(5, 3, 1, 4, 2)
val maxNumber = numbers.max(Ordering[Int])
val minNumber = numbers.min(Ordering[Int])
println(maxNumber) // 输出 5
println(minNumber) // 输出 1
上述代码中,Ordering[Int]
被用于进行整数的比较、排序和查找最值操作。
需要注意的是,Ordering[Int]
是一个隐式值(implicit value),因此在大多数情况下,你不需要显式地提供它。Scala 编译器会自动查找可用的 Ordering[Int]
实例。
在 Scala 中,集合计算的高级函数是指那些可以对集合进行高阶操作和转换的函数。这些高级函数是函数式编程的核心概念之一,可以让我们以简洁而优雅的方式处理集合数据。
以下是 Scala 中常用的几个集合计算的高级函数:
val numbers = List(1, 2, 3, 4, 5)
val squares = numbers.map(x => x * x) // 对每个元素求平方
val numbers = List(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter(x => x % 2 == 0) // 筛选出偶数
val numbers = List(1, 2, 3, 4, 5)
val sum = numbers.reduce((x, y) => x + y) // 所有元素求和
val numbers = List(1, 2, 3, 4, 5)
val sum = numbers.fold(0)((x, y) => x + y) // 所有元素求和,初始值为0
除了以上几个常用的高级函数,Scala 还提供了更多丰富的集合计算函数,比如 flatMap、groupBy、sortBy、zip 等,它们可以满足更多不同的集合操作需求。
flatMap、groupBy、sortBy、zip 这几个函数的作用和用法:
val words = List("Hello", "World")
val letters = words.flatMap(word => word.toList) // 将每个单词转换为字符列表,并展平为一个字符列表
val numbers = List(1, 2, 3, 4, 5)
val grouped = numbers.groupBy(number => number % 2) // 根据奇偶性分组
执行上述代码后,grouped
的结果为 Map(0 -> List(2, 4), 1 -> List(1, 3, 5))
,其中键 0 表示偶数,键 1 表示奇数。
val numbers = List(5, 3, 1, 4, 2)
val sorted = numbers.sortBy(number => number) // 按照升序排序
val letters = List('A', 'B', 'C')
val numbers = List(1, 2, 3)
val zipped = letters.zip(numbers) // [('A', 1), ('B', 2), ('C', 3)]
上述代码中,letters
和 numbers
分别配对形成了 zipped
,根据索引位置一一对应。
这些高级函数可以帮助我们在处理集合数据时更加灵活和高效。通过使用它们,我们可以以更简洁的方式完成常见的集合操作。
object Test14_HighLevelFunction_Map {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5,6,7,8,9)
// 1. 过滤
// 选取偶数
val evenList = list.filter( (elem: Int) => {elem % 2 == 0} )
println(evenList)
// 选取奇数
println(list.filter( _ % 2 == 1 ))
println("=======================")
// 2. 映射map
// 把集合中每个数乘2
println(list.map( elem => elem * 2 ))
//简化如下:
println(list.map(_ * 2))
println(list.map( x => x * x))
println("=======================")
// 3. 扁平化
val nestedList: List[List[Int]] = List(List(1,2,3),List(4,5),List(6,7,8,9))
val flatList = nestedList(0) ::: nestedList(1) ::: nestedList(2)
println(flatList)
val flatList2 = nestedList.flatten
println(flatList2)
println("=========先对集合map映射操作,然后扁平化flatten操作:==============")
// 4. 扁平映射
// 将一组字符串进行分词,并保存成单词的列表
val strings: List[String] = List("hello world", "hello scala", "hello java", "we study")
val splitList: List[Array[String]] = strings.map( _.split(" ") ) // 分词
val flattenList = splitList.flatten // 打散扁平化
println(flattenList)
println("------------直接使用flatMap函数扁平化-----------------")
// 使用flatMap函数,可以直接对字符串数组进行打散,然后扁平化。参数是函数,定义打散的规则,也就是切词规则
val flatmapList = strings.flatMap(_.split(" "))
println(flatmapList)
println("========================")
/*
5. 分组groupBy函数,返回的是一个不可变Map集合:immutable.Map[K, Repr]
groupBy函数解读:
函数用于根据指定的分类函数将集合中的元素分组,并生成一个不可变的 Map,其中键是根据分类函数计算的结果,值是对应的元素列表。
例子:val groupMap2: Map[String, List[Int]] = list.groupBy( data => if (data % 2 == 0) "偶数" else "奇数")
*/
// 分成奇偶两组
val groupMap: Map[Int, List[Int]] = list.groupBy( _ % 2)
println("分组不指定分类函数计算结果对应的键值: " + groupMap)
/**
* 打印的结果是:Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
*/
val groupMap2: Map[String, List[Int]] = list.groupBy( data => if (data % 2 == 0) "偶数" else "奇数")
println(groupMap2)
// 给定一组词汇,按照单词的首字母进行分组
val wordList = List("china", "america", "alice", "canada", "cary", "bob", "japan")
println( wordList.groupBy( _.charAt(0) ) )
}
}
List(2, 4, 6, 8)
List(1, 3, 5, 7, 9)
=======================
List(2, 4, 6, 8, 10, 12, 14, 16, 18)
List(2, 4, 6, 8, 10, 12, 14, 16, 18)
List(1, 4, 9, 16, 25, 36, 49, 64, 81)
=======================
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
List(1, 2, 3, 4, 5, 6, 7, 8, 9)
=========先对集合map映射操作,然后扁平化flatten操作:==============
List(hello, world, hello, scala, hello, java, we, study)
------------直接使用flatMap函数扁平化-----------------
List(hello, world, hello, scala, hello, java, we, study)
========================
分组不指定分类函数计算结果对应的键值: Map(1 -> List(1, 3, 5, 7, 9), 0 -> List(2, 4, 6, 8))
Map(奇数 -> List(1, 3, 5, 7, 9), 偶数 -> List(2, 4, 6, 8))
Map(b -> List(bob), j -> List(japan), a -> List(america, alice), c -> List(china, canada, cary))
def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
val m = mutable.Map.empty[K, Builder[A, Repr]]
for (elem <- this) {
val key = f(elem)
val bldr = m.getOrElseUpdate(key, newBuilder)
bldr += elem
}
val b = immutable.Map.newBuilder[K, Repr]
for ((k, v) <- m)
b += ((k, v.result))
b.result
}
源码解读:
这段代码是 Scala 标准库中的 groupBy
函数的实现。groupBy
函数用于根据指定的分类函数将集合中的元素分组,并生成一个不可变的 Map,其中键是根据分类函数计算的结果,值是对应的元素列表。
让我们逐行解释这段代码的含义:
def groupBy[K](f: A => K): immutable.Map[K, Repr] = {
:这是一个泛型方法定义,接受一个类型为 A => K
的函数 f
,返回一个不可变的 Map。
val m = mutable.Map.empty[K, Builder[A, Repr]]
:创建一个空的可变 Map m
,用于存储分组后的元素。
for (elem <- this) {
:对集合中的每个元素执行循环。
val key = f(elem)
:使用分类函数 f
对当前元素 elem
进行计算,得到分类的键 key
。
val bldr = m.getOrElseUpdate(key, newBuilder)
:从 Map m
中获取键为 key
的值,如果不存在则创建一个新的 Builder,并将其存储到 Map m
中,然后将其赋值给变量 bldr
。
bldr += elem
:将当前元素 elem
加入到对应键所对应的 Builder 中。
val b = immutable.Map.newBuilder[K, Repr]
:创建一个新的不可变 Map 的建造器 b
。
for ((k, v) <- m)
:对 Map m
中的每个键值对执行循环。
b += ((k, v.result))
:将键值对 (k, v.result)
加入到不可变 Map 的建造器 b
中,其中 v.result
是 Builder 中存储的元素的结果(即分组后的元素列表)。
b.result
:获取不可变 Map 的最终结果,并返回。
总之,以上代码实现了将集合中的元素根据分类函数进行分组,并生成一个不可变的 Map。这个函数在实际开发中非常有用,可以方便地进行数据分组和聚合操作。
object Test15_HighLevelFunction_Reduce {
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4)
// 1. reduce
println(list.reduce( _ + _ ))
println(list.reduceLeft(_ + _))
println(list.reduceRight(_ + _))
println("===========================")
val list2 = List(3,4,5,8,10)
println(list2.reduce(_ - _)) // -24
println(list2.reduceLeft(_ - _))
println(list2.reduceRight(_ - _)) // 3 - (4 - (5 - (8 - 10))), 6
println("===========================")
// 2. fold
println(list.fold(10)(_ + _)) // 10 + 1 + 2 + 3 + 4
println(list.foldLeft(10)(_ - _)) // 10 - 1 - 2 - 3 - 4
println(list2.foldRight(11)(_ - _)) // 3 - (4 - (5 - (8 - (10 - 11)))), -5
}
}
reduce源码解读:
reduce
方法是 Scala 集合中的一个高阶函数,用于将集合中的元素进行聚合。下面是 reduce
方法的源码解读:
def reduce[A1 >: A](op: (A1, A1) => A1): A1 = {
if (isEmpty)
throw new UnsupportedOperationException("empty.reduce")
var first = true
var acc: A1 = 0.asInstanceOf[A1]
for (x <- self) {
if (first) {
acc = x
first = false
}
else acc = op(acc, x)
}
acc
}
首先,reduce
方法接受一个二元函数 op
,类型为 (A1, A1) => A1
,用于将集合中的元素进行聚合。在 Scala 中,二元函数是一种函数类型,接受两个相同类型的参数,返回一个与参数类型相同的结果值。
二元函数是一个接受两个相同类型参数并返回相同类型结果的函数。在 fold 方法中,二元函数 op 用于将集合中的元素进行聚合、累积或操作。
如果集合为空,则会抛出 UnsupportedOperationException
异常。
接着,方法定义了一个名为 first
的变量,初值为 true
,表示当前聚合的是第一个元素。另外,定义了一个名为 acc
的变量,初值为 0
,它表示聚合的结果。
接下来,reduce
方法使用 for 循环遍历集合中的每个元素。对于第一个元素,将其赋值给 acc
变量。对于第二个及之后的元素,将它们分别与 acc
变量进行二进制操作,更新 acc
变量的值。
最后,reduce
方法返回聚合的结果。
例如,以下代码使用 reduce
表示计算所有元素的和:
val list = List(1, 2, 3, 4, 5)
val sum = list.reduce(_ + _)
println(sum) // 输出 15
这里的 _ + _
表示一个匿名函数,它接受两个整数参数并返回它们的和。
需要注意的是,reduce
方法的工作原理是将集合中的元素两两进行操作,因此操作符必须是可交换和关联的。否则,聚合结果可能会出现意外的错误。
二元函数是一个接受两个相同类型参数并返回相同类型结果的函数。在 fold 方法中,二元函数 op 用于将集合中的元素进行聚合、累积或操作。
如果集合为空,则会抛出 UnsupportedOperationException
异常。
fold函数源码解读:
fold
是 Scala 集合中提供的一个高阶函数,用于将集合中的元素进行折叠(折叠也可以称为累积、聚合)操作。下面是 fold
方法的源码解读:
def fold[A1 >: A](z: A1)(op: (A1, A1) => A1): A1 = {
var acc = z
for (x <- self) acc = op(acc, x)
acc
}
首先,fold
方法接受两个参数:一个初始值 z
和一个二元函数 op
。初始值 z
表示折叠的起始值,而二元函数 op
表示对两个相同类型的值进行操作并返回结果。
然后,方法定义了一个名为 acc
的变量,用于存储折叠的结果。初始时,将 acc
的值设置为初始值 z
。
接下来,fold
方法使用 for 循环遍历集合中的每个元素,并使用二元函数 op
对当前元素和 acc
进行操作,更新 acc
变量的值。
最后,fold
方法返回折叠的结果。
例如,以下代码使用 fold
方法计算所有元素的乘积:
val list = List(1, 2, 3, 4, 5)
val product = list.fold(1)(_ * _)
println(product) // 输出 120
这里的 1
是初始值,表示折叠的起始值。而 _ * _
表示一个匿名函数,它接受两个整数参数并返回它们的乘积。
需要注意的是,fold
方法可以用于任何类型的集合,包括数组、列表、映射等。它提供了一种通用的方式来对集合进行折叠操作。
代码示例
object Test16_MergeMap {
def main(args: Array[String]): Unit = {
val map1 = Map("a" -> 1, "b" -> 3, "c" -> 6)
val map2 = mutable.Map("a" -> 6, "b" -> 2, "c" -> 9, "d" -> 3)
// println(map1 ++ map2)
/**
* def foldLeft[B](z: B)(op: (B, A) => B): B ={...}
* foldLeft( 初始化值map2 )( (mergedMapResult 当前聚合的结果, KV是 map1中的kv键值对 ) => {} )
*
*/
val map3 = map1.foldLeft(map2)(
(mergedMapResult, kv) => {
val key = kv._1
val value = kv._2
// 从当前聚合的结果Map集合中通过key获取值,如果有这个可以则将对应map1的相同key的值累加,没有对应的key默认值为0
mergedMapResult(key) = mergedMapResult.getOrElse(key, 0) + value
mergedMapResult
}
)
println(map3)
}
}