13_Scala_数据结构下_集合操作
高阶函数
object HighOrderT1 {
def main(args: Array[String]): Unit = {
//在scala中,可以把一个函数直接赋给一个变量,但是不执行函数 (myPrint _)
val m1 = myPrint _
println(m1 ) //com.chapter11_Array_Func.HighOrderT1$$$Lambda$1/1149319664@17ed40e0
m1() //执行 myPrint() 输出 hello
//函数直接赋给一个变量,但是不执行函数 addSum _
val i = Htest(addSum _, 30)
println(i) //60
Htest2(myPrint) //hello
}
def myPrint(): Unit = {
println("hello")
}
def Htest (f: Int=> Int, num: Int) = {
f(num)
}
def addSum (i: Int) : Int = {
i * 2
}
//说明Htest2是一个高阶函数,可以接受一个 没有输入,返回为Unit的函数
def Htest2(f: ()=>Unit): Unit = {
f()
}}
map映射操作
在Scala中通过map映射解决:集合中的每一个元素通过指定功能(函数)映射(转换)成新集合
将函数作为参数传递给另外一个函数,这是函数式编程的特点
object MapTest1 {
def main(args: Array[String]): Unit = {
val list1 = List(10,20,30,40)
//1. 将list1这个集合的元素 依次遍历 将各个元素传递给 multiple 函数 => 新Int
//2. 将得到新Int ,放入到一个新的集合并返回 multiple 函数调用4次
val list2 = list1.map(multiple)
println(list2) //List(20, 40, 60, 80)
//1. 将names这个集合的元素 依次遍历 将各个元素传递给 stringTrans 函数 => 新String
//2. 将得到新String ,放入到一个新的集合并返回 names_new
val names = List("Alex", "Bob", "Sully")
val names_new = names.map(stringTrans)
println(names_new) //List(ALEX, BOB, SULLY)
}
def multiple(n:Int): Int = {
println("multiple 被调用~~")
2 * n}
def stringTrans(s: String) : String ={
s.toUpperCase()}
}
flatmap:flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。
filter:将符合要求的数据(筛选)放置到新的集合中; filter 要求函数返回 boolean
object MapTest1 {
def main(args: Array[String]): Unit = {
val list1 = List(10,20,30,40)
//1. 将list1这个集合的元素 依次遍历 将各个元素传递给 multiple 函数 => 新Int
//2. 将得到新Int ,放入到一个新的集合并返回 multiple 函数调用4次
val list2 = list1.map(multiple)
println(list2) //List(20, 40, 60, 80)
//1. 将names这个集合的元素 依次遍历 将各个元素传递给 stringTrans 函数 => 新String
//2. 将得到新String ,放入到一个新的集合并返回 names_new
// A => B String => B
val names = List("Alex", "Bob", "Sully")
val names_new = names.map(stringTrans)
println(names_new) //List(ALEX, BOB, SULLY)
// flatmap 将集合中的每个元素的子元素映射到某个函数并返回新的集合
// 进行扁平化操作,即把所有元素打散
// A => IterableOnce[B] string => IterableOnce[B]
val names_flat = names.flatMap(stringTrans)
println(names_flat) //List(A, L, E, X, B, O, B, S, U, L, L, Y)
// Filter A => Boolean A 泛型; String => Boolean
// 数据(筛选)放置到新的集合中
val names_filter = names.filter(stringeql)
println(names_filter) //List(Alex)
}
def multiple(n:Int): Int = {
println("multiple 被调用~~")
2 * n}
def stringTrans(s: String) : String ={
s.toUpperCase()}
def stringeql(s: String) : Boolean ={
s.startsWith("A")
}
}
化简 reduce - 二元函数引用于集合中的函数
object ReduceTest1 {
def main(args: Array[String]): Unit = {
//简化 求和
//def reduceLeft[B >: A](op: (B, A) => B): B
//reduceLeft(f) 接收的函数需要的形式为 op: (B, A) => B): B 理解为 传个函数(俩参数) 返回一个值(给left or right)
//reduceleft(f) 的运行规则是 从左边开始执行将得到的结果返回给第一个参数 //步骤1 (1 + 2)
// 再和下一个元素运行,继续返回给第一个参数 //步骤2 (1 + 2) + 3
val list1 = List(1, 2, 3)
val result = list1.reduceLeft(addSum)
println(result)
val list2 = List(10, 20, 30)
println(list2.reduceLeft(mins)) // -40 (10-20) -30
println(list2.reduceRight(mins)) // 20 10- (20-30)
//最小值
val list3 = List(100, 20, 30)
println( list3.reduceLeft(minValue) ) //20
}
def addSum(i1: Int, i2: Int) :Int = {
i1 + i2}
def mins (j1: Int, j2: Int): Int ={
j1 - j2}
def minValue(x1: Int, x2: Int) : Int = {
if (x1 > x2) x2 else x1
}
}
折叠 fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历(相关函数 fold,foldLeft,foldRight)
object FoldTest1 {
def main(args: Array[String]): Unit = {
val list1 = List(1, 2, 3, 4)
// 函数的柯里化
// 源码:
//override def foldLeft[B](z: B)(op: (B, A) => B): B = {
// var acc = z ; var these: LinearSeq[A] = coll //定义一个集合
// while (!these.isEmpty) {
// acc = op(acc, these.head) //op(acc,集合第一个元素) 返回值-> acc
// these = these.tail } // 集合 为 these tail (出去head 剩余元素)
// acc // 返回acc
// }
//(20-1) -1 -> ((20-1) -1) -2 ....
val result1 = list1.foldLeft(20)(mins) //20
println(result1) //10
val result2 = list1.foldRight(20)(mins)
println(result2 ) //18 (4-20) -> 3-(4-20) #19-> 2 -19 #-17 -> 1-(-17) 18
}
def mins(i1: Int, i2: Int) :Int = {
i1 - i2}
}
扫描,scan 即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存
object ScanTest {
def main(args: Array[String]): Unit = {
//扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存
// (1 to 5) 遍历,先把 5 保留下来 (5, ) 然后再 开始fold(1,2,3,4,5) -> (5, 4, 2, -1, -5, -10)
val result = (1 to 5).scanLeft(5)(minus) //IndexedSeq[Int]
println("result=" + result) // 返回一个IndexSeq[] 索引序列
// ( 50) 右flod (1,2,3,4,5) -> ( 1-8 ,2-(-6) ,3-9 ,4-(-5) , -5, 10)
var result_right = (1 to 5).scanRight(10)(minus)
println(result_right) //Vector(-7, 8, -6, 9, -5, 10)
}
def minus( num1 : Int, num2 : Int ) : Int = {
num1 - num2
}
}
扩展 Others
拉链 zip (对偶元组合并) 本质就是两个集合的合并操作,合并后每个元素是一组 对偶元组
迭代器 iterator 方法从集合获得一个迭代器 hasNext next()
object OthersTest {
def main(args: Array[String]): Unit = {
//本质就是两个集合的合并操作,合并后每个元素是一组 对偶元组
//两个集合个数不对应,会造成数据丢失 不限于List, 也可以是其它集合(Array)
val list1 = List(1, 2, 3)
val list2 = List(11, 22, 33)
val list3 = list1.zip(list2) //List((1,11), (2,22), (3,33))
println("list3=" + list3)
//如果要取出合并后的各个对偶元组的数据,可以遍历
for (item <- list3){
println(item._1 + " - "+ item._2) //1 - 11
}
// 迭代器 通过iterator方法从集合获得一个迭代器
val iterator = list1.iterator
while (iterator.hasNext){
println(iterator.next())
}
// 指针要重置下
val iterator2 = list1.iterator
for (ee <- iterator2) {
println(ee)}
}
}
stream是一个集合可以用于存放无穷多个元素,
但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循lazy规则
object StreamTest {
def main(args: Array[String]): Unit = {
def numsForm1(n: BigInt) : Stream[BigInt] = n #:: numsForm1(n + 1)
def numsForm2(n: BigInt): LazyList[BigInt] = n #:: numsForm2(n + 1)
//stream是一个集合。可以用于存放无穷多个元素,
// 但是这无穷个元素并不会一次性生产出来,而是需要用到多大的区间,就会动态的生产,末尾元素遵循lazy规则
val stream1 = numsForm1(10)
println("head=" + stream1.head) //head=10
println(stream1.tail) //Stream(11, <not computed>)
println(stream1) //Stream(10, 11, <not computed>)
val stream2 = numsForm2(10)
println("head=" + stream1.head) //head=10
println(stream2.tail) //LazyList(<not computed>)
println(stream2) //LazyList(10, <not computed>)
}
}
view方法产出一个总是被懒执行的集合。
view不会缓存数据,每次都要重新计算,比如遍历View
object ViewTest {
def main(args: Array[String]): Unit = {
val viewSquares1 = (1 to 50).filter(eq)
println(viewSquares1) //Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44)
//使用view,来完成这个问题,程序中,对集合进行map,filter,reduce,fold...
//你并不希望立即执行,而是在使用到结果才执行,则可以使用view来进行优化.
val viewSquares2 = (1 to 30).view.filter(eq)
println(viewSquares2) //View(<not computed>) filter并未执行 待真正调用时候执行
//eq 被调用.. 10 调用 未打印
//eq 被调用.. 11 调用 打印出来
//11
for (item <- viewSquares2){ // 操作viewSquare2 时候 filter才会生效
println(item)}
}
def multiple(num: Int): Int = {
num}
def eq(i: Int): Boolean ={
println("eq 被调用..")
i.toString.equals(i.toString.reverse)
}
}
线程安全的集合
SynchronizedBuffer
SynchronizedMap
SynchronizedPriorityQueue
SynchronizedQueue
SynchronizedSet
SynchronizedStack
并行集合
Scala为了充分使用多核CPU,提供了并行集合
主要用到的算法有:
Divide and conquer : 分治算法,Scala通过splitters(分解器),combiners(组合器)等抽象层来实现,
主要原理是将计算工作分解很多任务,分发给一些处理器去完成,并将它们处理结果合并返回Work stealin算法,
主要用于任务调度负载均衡(load-balancing)
object ParDemo01 {
def main(args: Array[String]): Unit = {
(1 to 5).foreach(println(_))
println()
//这里输出的结果是无序的,说明是将println任务分配给不同cpu
(1 to 5).par.foreach(println(_))
val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}.distinct // 始终是主线程
val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}.distinct // 不同线程
println(result1) //非并行
println("--------------------------------------------")
println(result2) //并行
}
}
- 点赞
- 收藏
- 关注作者
评论(0)