高阶函数和 Map 映射 | 学习笔记

简介: 快速学习高阶函数和 Map 映射

开发者学堂课程【Scala 核心编程 - 进阶高阶函数和 Map 映射学习笔记,与课程紧密连接,让用户快速学习知识。

课程地址https://developer.aliyun.com/learning/course/610/detail/9048


高阶函数和 Map 映射


内容介绍:

一、map 映射操作

二、高阶函数的基本使用

三、使用 map 映射函数来解决

四、深刻理解 map 映射函数的机制-模拟实现


一、map 映射操作

上节提出的问题,其实就是一个关于集合元素映射操作的问题。

Scala 中可以通过 map 映射操作来解决:将集合中的每一个元素通过指定功能就是函数,函数是一系列代码完成一个功能的集合,映射(转换)成新的结果集合这里其实就是所谓的将函数作为参数传递给另外一个函数这是函数式编程的特点

1.HashSet 为例说明

def map[B](f:(A)→ B): HashSet[B]  //map 函数的签名

1)这个就是map映射函数集合类型都有

2)[B]是泛型

3) map 是一个高阶函数(高阶函数是可以接收一个函数的函数),可以接收函数f:(A)=>B后面详解(先简单介绍下),接收函数(A)的类型是可以传入一个值,这个值是泛型,也可以返回一个值,这个值的也是泛型(B)

4)HashSetTB1就是回的新的集合


二、高阶函数的基本使用

1.代码及说明

object HighorderFunDemoo1 {

def main( args : Array [string]): unit = {

//使用高阶函数

val res = test(sum2,3.5)

println(“res=”+res)

//传入一个函数,所以无需在 sum2 后面写小括号,sum() 代表执行

}

//说明

//1. test就是一个高阶函数

//2. f: Double =>Double 表示一个函数,该函数可以接受一个//DoubLe,返回DoubLe

//3. ni : Double普通参数

//4. f(n1) 代表在 test 函数中执行要传入的函数,要传入的函数要//满足下面函数的签名

//可以理解为,如果画一个底层的画,类似于 f 指向了这个函数的地//址,之后对函数参数进行使用

def test (f : Double => Double,n1: Double) = {

f(n1)  

}

//普通的函数

def sum2 (d : Double) : Double = {

//这个函数满足上面签名的需要

d + d

}

}

运行结果为:

res=7.0

在该程序中,sum2 这个函数被调用,说明该程序中一个函数调用了另一个函数,如何理解?

下面的示意图帮助理解传函数这种参数的一种机制。

这是一块内存,有三个核心区块,栈区、堆区、方法区。

image.png

以下两个函数属于一个类,先后被加载

def test (f : Double => Double,n1: Double) = {

f(n1)  

}

当在栈中执行下面的代码后

val res = test(sum2,3.5)

sum2 的地址传给了 f ,相当于进入了下面的代码中

def sum2 (d : Double) : Double = {

d + d

}

可以理解为 f 指向 sum2 这段代码块,如何f(n1) 会调用下面代码的内容

def sum2 (d : Double) : Double = {

d + d

}

(简单理解为 f 是指向 sum2 的地址,函数本身也有地址,函数是共用的)

2.另一种传递方式

有时可以看到部分程序员这样传递 :val res = test(sum2_,3.5)

这样传递运行结果不变(下划线代表将一个函数传递)

如何理解这种传递方式,下面的案例说明帮助理解:

object HighorderFunDemoo1 {

def main( args : Array [string]): unit = {

val res = test(sum2,3.5)

println(“res=”+res)

//在 Scala 中也可以直接将一个函数赋给一个变量

//如果这里是val f1= myPrint ,则相当于执行这个函数将 //myPrint 的结果返回 f1,在很多情况下,想把一个函数赋给一个//变量,但是不想执行这个变量,所以可以用下划线操作,

如下

val f1= myPrint_ 

//将一个函数赋给一个变量但是不执行该函数,此时 f1 的类型是一个没有形参 Unit 函数

}

def myPrint(): Unit={

println(“hello,world!”)

def test (f : Double => Double,n1: Double) = {

f(n1)  

}

def sum2 (d : Double) : Double = {

println(“sum2 被调用”)

d + d

}

}

运行结果为:

sum2 被调用

res=7.0

发现没有输出 hello,world! ,说明实现了将一个函数赋给一个变量但是不执行该函数

3.为进一步理解,下面举一个高阶函数的案例

//传入无参的高阶函数

object HighOrderFunDemo02 {

def main(args: Array [string]) : unit = {

}

//如果想让高阶函数接收一个无参的函数,写法为如下

//说明 test2 是一个高阶函数,可以接收一个没有输入,返回为 //Unit 的函数

def test2(f: () => unit) = {

f()

}

def sayOK ()= {

printLn( "sayOKKK...")}

}

}

运行结果为:

sayOKKK...

注意:

传入的类型要匹配,比如需要传入一个无参的函数,如果传入其他函数会报错,

举个例子:

object HighOrderFunDemo02 {

def main(args: Array [string]) : unit = {

test2(sayOK)

test2(sub)      

//此时会报错,期望函数与实际传入函数不匹配

}

def test2(f: () => unit) = {

f()

}

def sayOK ()= {

printLn( "sayOKKK. ..")}

}

def sub(n1:Int):Unit={

}

}


三、使用 map 映射函数来解决

object MapoperateDemoo2 {

def main(args: Array [string]): unit = {

/*

请将List(3,5,7)中的所有元素都*2,

将其结果放到一个新的集合中返回,即返回一个新的List(6,10,14),请编写程序实现.

*/

val list = List( 3,5,7)

//说明:

// list.map(multiple) 做了什么

//1.将 list 集合的元素依次遍历

//2.将各个元素传递给 multiple 函数=> Int

//3.将得到新的Int ,放入到应该新的集合并返回

//4.因此 multiple 函数会被调用3次,如果元素个数更多,则被调//用的次数也更多

list.map(multiple)

val list2=list.map(multiple)

println(“list2=”+list2)  //此时应该返回为 list(6,10,14)

}

def multiple(n: Int ) : Int = {

2* n

}

}

运行结果为:list(6,10,14)

证明说明4

注意:

map 其实会接收两个值,B That 都是泛型,如下图可知,可以接收一个 Int 类型返回一个 B 类型的函数。

image.png


四、深刻理解 map 映射函数的机制-模拟实现

//底层代码

object MapoperateDemoo2 {

def main(args: Array [string]): unit = {

val list = List( 3,5,7,9)

list.map(multiple)

val list2=list.map(multiple)

println(“list2=”+list2)

val myList=MyList

println(myList)

}

def multiple(n: Int ) : Int = {

2* n

}

}

class MyList{

val list1=List(3,5,7,9)  

//这里可以写一个构造器,动态的传入数据,因为时间关系,将数据//固定并且都为整型

val list2=List[Int]()    

//新的空集合

//写 map

//注意 map 最后返回的结果是一个集合,def map():Unit 括号里//面可以是泛型的函数

def map(Int=>Int):List[Int]={  

//接收一个整数再返回一个整数

//遍历集合

for(item<-this.list1 //item 此时是集合里面的各个元素

list2=list2:+f(item)    // f 传入item

}

list2

}

}

object MyList{

def apply(): MyList =new MyList()

}

运行结果为:

list2= List(6,10,14,18)

com.atguigu.chapter11.MyList$@7f3425a

说明该机制没问题,接下来用该机制来完成

object MapoperateDemoo2 {

def main(args: Array [string]): unit = {

val list = List( 3,5,7,9)

list.map(multiple)

val list2=list.map(multiple)

println(“list2=”+list2)

val myList=MyList()

val myList2=myList.map(multiple)

println(“myList2”+ myList2)

}

def multiple(n: Int ) : Int = {

2* n

}

}

class MyList{

val list1=List(3,5,7,9)  

val list2=List[Int]()  

def map(Int=>Int):List[Int]={  

for(item<-this.list1 //item 此时是集合里面的各个元素

list2=list2:+f(item)    // f 传入item

}

list2

}

}

object MyList{

def apply(): MyList =new MyList()

}

运行结果为:

myList2= List(6,10,14,18)

到此已经将底层模拟机制完成,但是这段代码和真正的底层还是有区别,真正的底层可能做了一些优化,算法处理。

这里是直接的遍历处理,将来下面这段代码会有很多工作:

def map(Int=>Int):List[Int]={  

for(item<-this.list1 

list2=list2:+f(item)    

}

Scala 这种机制可以做很多工作,比如过滤(遍历过后再进行过滤),或者扁平化。

相关文章
|
4月前
|
Go
go语言中遍历映射(map)
go语言中遍历映射(map)
110 8
|
3月前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
84 12
|
4月前
|
存储 Go
go语言 遍历映射(map)
go语言 遍历映射(map)
59 2
|
9月前
|
Python
高阶函数如`map`, `filter`, `reduce`和`functools.partial`在Python中用于函数操作
【6月更文挑战第20天】高阶函数如`map`, `filter`, `reduce`和`functools.partial`在Python中用于函数操作。装饰器如`@timer`接收或返回函数,用于扩展功能,如记录执行时间。`timer`装饰器通过包裹函数并计算执行间隙展示时间消耗,如`my_function(2)`执行耗时2秒。
45 3
|
5月前
|
前端开发 JavaScript 索引
JavaScript 数组常用高阶函数总结,包括插入,删除,更新,反转,排序等,如map、splice等
JavaScript数组的常用高阶函数,包括遍历、插入、删除、更新、反转和排序等操作,如map、splice、push、pop、reverse等。
36 0
|
6月前
|
Go
Golang语言之映射(map)快速入门篇
这篇文章是关于Go语言中映射(map)的快速入门教程,涵盖了map的定义、创建方式、基本操作如增删改查、遍历、嵌套map的使用以及相关练习题。
58 5
|
7月前
|
分布式计算 Python
【python笔记】高阶函数map、filter、reduce
【python笔记】高阶函数map、filter、reduce
|
8月前
|
存储 算法 C++
C++一分钟之-扁平化映射与unordered_map
【7月更文挑战第5天】C++的STL `unordered_map`是键值对的快速查找容器,基于哈希表。常见问题包括哈希函数选择、键类型限制、内存管理和迭代顺序不确定性。要避免问题,需优化哈希函数,确保自定义类型支持哈希和比较操作,合理管理内存,不依赖迭代顺序。提供的代码示例展示了如何为自定义类型定义哈希函数并操作`unordered_map`。正确使用能提升代码效率。
102 0
C++一分钟之-扁平化映射与unordered_map
|
9月前
|
Python
在Python中,`map()`, `filter()` 和 `reduce()` 是函数式编程中的三个核心高阶函数。
【6月更文挑战第24天】Python的`map()`应用函数到序列元素,返回新序列;`filter()`筛选满足条件的元素,生成新序列;`reduce()`累计操作序列元素,返回单一结果。
56 3
|
9月前
|
存储 算法 C++
C++一分钟之-扁平化映射与unordered_map
【6月更文挑战第30天】`std::unordered_map`在C++中提供O(1)平均操作的无序键值对存储。文章讨论了扁平化映射,用于简化多级数据结构,例如将配置文件展平。常见问题包括哈希碰撞、内存管理和键类型选择。示例展示了如何创建和访问扁平化配置映射。通过理解哈希冲突解决、内存管理和键要求,可以优化使用。
88 0