Scala是函数式编程,这点在集合操作中大量体现。高阶函数,也就是能够接收另外一个函数作为参数的函数。

假如现在有一个需要是将List集合中的每个元素变为原来的两倍,现在来对比Java方式实现和Scala方式实现区别

Java方式实现,先将集合中的每个元素遍历出来,然后再乘以2,塞到另外一个集合中

  1. ArrayList<Integer> list1 = new ArrayList<Integer>();
  2. list1.add(3);
  3. list1.add(5);
  4. list1.add(7);
  5. ArrayList<Integer> list2 = new ArrayList<Integer>();
  6. for (Integer elem : list1) {
  7. list2.add(elem * 2);
  8. }
  9. System.out.println(list2);

  

Scala方式实现

  1. val list1 = List(3, 5, 7)
  2. val list2 = list1.map(multiple) //map高阶函数,能够接收另外一个函数
  3. def multiple(n1: Int): Int = {
    2 * n1
    }
    println(list2)

可以发现相对于Java的实现方式,Scala中更偏向于使用高阶函数来解决问题,并且也简化了很多。

或许你会有些许疑问,这是什么鬼,这没有简化到哪里呀!的确,但是这里只是小小的演示。  

Scala中常用的高阶函数有如下几种

1.映射函数(map)

map函数

小注:在Scala中的泛型是表示方法是“[]”,java中的泛型表示方式是“<>”。map函数存在于所有集合类型中,包括在String中。

现在再看前面的实例,它是这样来执行的

  1. 首先依次遍历list1集合的元素
  2. 将各个元素传递给Multiple函数,计算并返回
  3. 将返回结果放到一个新的集合中,并赋给list2
  4. 输出结果

为了能够更好的理解,尝试编写一个List,来模拟List

  1. object Demo_021{
  2. def main(args: Array[String]): Unit = {
  3. val myList = MyList()
  4. val myList2 = myList.map(multiple) //调用map高阶函数,并传入mutiple函数
  5. println("myList2=" + myList2)
  6. println("myList=" + myList.list1)
  7. }
  8. def multiple(n1: Int): Int = {
  9. 2 * n1
  10. }
  11. }
  12. //伴生类,模拟List
  13. class MyList {
  14. var list1 = List(3, 5, 7)
  15. var list2 = List[Int]()
  16. //map高阶函数,接收另外一个函数作为参数,
  17. // f:Int=>Int : f表示是函数,:Int表示所传入的函数f的参数类型,必须是Int型,=>Int表示所传入函数f的返回值为Int
  18. // : List[Int] :表示Map函数的返回值为List[Int]
  19. def map(f:Int=>Int): List[Int] = {
  20. for (item<-list1) {
  21. list2 = list2 :+ f(item) //f(item) 表示调用所传入的函数,每次执行都会将返回写过写入到list2中
  22. }
  23. list2 //返回list2,未明确指定返回值,以函数最后一行的执行结果作为返回值
  24. }
  25. }
  26. //伴生对象
  27. object MyList {
  28. //使用apply方式实例化
  29. def apply(): MyList = new MyList()
  30. }

  

运行结果:

模拟有些拙劣,但是基本能够说明问题,map方法在List底层所实现时,也是逐个遍历并执行所传入的函数,最后返回执行结果集合

下面是List中map函数的源码,实际List集合底层在调用map方法的时候所做的操作和上面类似

使用实例1:将 val names = List("Alice", "Bob", "Nick") 中的所有单词,全部转成字母大写,返回到新的List集合中.

  1. object Demo_022 {
  2. def main(args: Array[String]): Unit = {
  3. val names = List("Alice", "Bob", "Nick")
  4. val names2 = names.map(upper)
  5. println("names=" + names2)
  6. }
  7. def upper(s:String): String = {
  8. s.toUpperCase
  9. }
  10. }

  执行结果:

2.扁平化(flatMap)

flatmap:所谓扁平化,就是将集合中的每个元素的子元素映射到某个函数并返回新的集合。

实例:

  1. object Demo_022 {
  2. def main(args: Array[String]): Unit = {
  3. val names = List("Alice", "Bob", "Nick")
  4. //相当于在原来map高阶函数的基础上做了二次循环,将元素进一步打散
  5. val names2 = names.flatMap(upper)
  6. println("names=" + names2)
  7. }
  8. def upper(s:String): String = {
  9. s.toUpperCase
  10. }
  11. }

  运行结果:

3.过滤(filter)

filter:将符合要求的数据(筛选)放置到新的集合中

应用案例:将  val names = List("Alice", "Bob", "Nick") 集合中首字母为'A'的筛选到新的集合。

  1. object Demo_025 {
  2. def main(args: Array[String]): Unit = {
  3. val names = List("Alice", "Bob", "Nick")
  4.  
  5. def startA(s: String): Boolean = {
  6. s.startsWith("A")
  7. }
  8.  
  9. val names2 = names.filter(startA) //表示调用filter高阶函数
  10. println("names=" + names2)
  11.  
  12. }
  13. }

 运行结果:

还有更为简洁的操作:

  1. // val names2: List[String] = names.filter((x:String)=>x.startsWith("A"))
  2. val names2: List[String] = names.filter(_.startsWith("A"))

  

filter函数在执行过程中,类似于map函数,将符合条件的筛选出来放到一个集合中。

4.化简(reduce、reduceLeft、reduceRight)

化简:将二元函数引用于集合中的函数。有三种类型的函数,reduce、reduceLeft和reduceRight,其中reduce等同于reduceLeft。

reduceLeft(f) 接收的函数需要的形式为 op: (B, A) => B): B,

reduceleft(f) 的运行规则是 从左边开始执行将得到的结果返回给第一个参数,然后继续和下一个元素运行,将得到的结果继续返回给第一个参数,继续.。

reduceRight的运行规则和reduceRight类似,只是从右往左执行

实例1:val list = List(1,2,3,4,5) , 求出list的和

  1. object Demo_026 {
  2. def main(args: Array[String]): Unit = {
  3. val list = List(1, 2, 3, 4, 5)
  4. def sum(n1: Int, n2: Int): Int = {
  5. n1 + n2
  6. }
  7. val res1 = list.reduceLeft(sum)
  8. println("res=" + res1)
  9. }
  10. } 

输出为60。

实例2:观察reduce、reduceRight和reduceLeft在求List(1, 2, 3, 4 ,5)中元素差值时的表现

  1. object Demo_027 {
  2. def main(args: Array[String]): Unit = {
  3. val list = List(1, 2, 3, 4 ,5)
  4. def minus( num1 : Int, num2 : Int ): Int = {
  5. num1 - num2
  6. }
  7. println(list.reduceLeft(minus)) // 输出-13
  8. println(list.reduceRight(minus)) //输出3
  9. println(list.reduce(minus)) //输出-13
  10.  
  11. }
  12. } 

运行结果为

综述:reduce等同于reduceLeft、执行规则从左向右,而reduceRight执行规则是从右向左。

另外,还可以使用化简来求出一个集合的最值

  1. object Demo_027 {
  2. def main(args: Array[String]): Unit = {
  3. val list = List(1, 2, 3, 4 ,5)
  4. def max( num1 : Int, num2 : Int ): Int = {
  5. if(num1<num2){
  6. num2
  7. }else{
  8. num1
  9. }
  10. }
  11. println(list.reduceLeft(max)) // 求list中的最大值
  12. }
  13. }

简化形式是:

  1. val result: Int = list.reduceLeft((num1,num2)=>{if(num1<num2) num2 else num1})

5.折叠(foldLeft、foldRight、fold)

fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历。有三种函数形式:fold、foldLeft和folderRight。

fold函数在使用上基本和reduce函数在使用上基本相同,甚至reduceLeft函数的底层,就是调用foldLeft函数

观察如下实例

  1. object Demo_028 {
  2. def main(args: Array[String]): Unit = {
  3. val list = List(1, 2, 3, 4)
  4. def minus(n1: Int, n2: Int): Int = {
  5. n1 - n2
  6. }
  7. println(list.foldLeft(5)(minus))
  8.  
  9. println(list.foldRight(5)(minus))
  1. } }

  输出结果为:

它的执行过程是这样的:

另外foldLeft和foldRight 缩写方式分别是:/:和:\

  1. object Demo_028 {
  2. def main(args: Array[String]): Unit = {
  3. val list = List(1, 2, 3, 4)
  4. def minus(n1: Int, n2: Int): Int = {
  5. n1 - n2
  6. }
  7. println((5 /: list)(minus)) //等价于list.foldLeft(5)(minus)
  8. println((list :\ 5)(minus)) //list.foldRight(5)(minus)
  9. }
  10. }

  可以使用folderLeft统计字母出现的次数,还可以用来统计文本中单词出现的次数

6.扫描(scanLeft、scanRight)

扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存

  1. object Demo_029 {
  2. def main(args: Array[String]): Unit = {
  3. def minus( num1 : Int, num2 : Int ) : Int = {
  4. num1 - num2
  5. }
  6. //5 (1,2,3,4,5) =>(5,4,2,-1,-5,-10)
  7. val i8 = (1 to 5).scanLeft(5)(minus) //IndexedSeq[Int]
  8. println(i8)
  9.  
  10. def add( num1 : Int, num2 : Int ) : Int = {
  11. num1 + num2
  12. }
  13. //5 (1,2,3,4,5) =>(5,6,8, 11,15,20)
  14. val i9 = (1 to 5).scanLeft(5)(add) //IndexedSeq[Int]
  15. println(i9)
  16.  
  17. }
  18. }

  输出结果为:

观察另外一个实例

  1. object Demo_030 {
  2. def main(args: Array[String]): Unit = {
  3. def test(num1:Int,num2:Int): Int ={
  4. num1 * num2
  5. }
  6. var result=(1 to 3).scanLeft(3)(test)
  7. println(result)
  8. }
  9. }

 运行结果

综述,scanLeft执行类似于folderLeft,只是它会将中间结果缓存下来。

Scala集合操作中的几种高阶函数的更多相关文章

  1. 学好Spark/Kafka必须要掌握的Scala技术点(三)高阶函数、方法、柯里化、隐式转换

    5. 高阶函数 Scala中的高阶函数包含:作为值的函数.匿名函数.闭包.柯里化等,可以把函数作为参数传递给方法或函数. 5.1 作为值的函数 定义函数时格式: val 变量名 = (输入参数类型和个 ...

  2. Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

    在上面一个章节中,详细的讲解了Kotlin中关于Lambda表达式的语法以及运用,如果还您对其还不甚理解,请参见Kotlin--高级篇(一):Lambda表达式详解.在这篇文章中,多次提到了Kotli ...

  3. Python之高阶函数如何理解?

    我们先要了解一下什么是所谓的高阶函数: 看定义:什么是高阶函数? 高阶函数:我们知道一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),如果满足 ...

  4. 12、python中的函数(高阶函数)

    一.高阶函数 函数实际上也是一个对象,所以也能由变量指向一个函数对象,实际上函数名就是一个变量名.那么函数是传入变量作为参数的,如果传入的变量指向的是函数对象,这种函数就叫高阶函数. 高阶函数就是传入 ...

  5. python(内置高阶函数)

    1.高阶函数介绍: 一个函数可以作为参数传给另外一个函数,或者一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归),如果满足其一,则为高阶函数. 常见的高阶函数:map().sorted( ...

  6. Scala高阶函数

    1.作为参数的函数 函数可以作为一个参数传入到一个方法当中去 def main(args: Array[String]): Unit = { val myFunc1 =(x:Int) =>{ x ...

  7. Python3基础(3)集合、文件操作、字符转编码、函数、全局/局部变量、递归、函数式编程、高阶函数

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...

  8. Thinking in scala (5)----高阶函数*

    高阶函数是函数式编程里面一个非常重要的特色,所谓的高阶函数,就是以其它函数作为参数的函数. 下面以一个小例子演示Scala的高阶函数特性,非常有意思,也非常强大. 首先看这么一个程序: code1: ...

  9. Scala - 快速学习08 - 函数式编程:高阶函数

    函数式编程的崛起 函数式编程中的“值不可变性”避免了对公共的可变状态进行同步访问控制的复杂问题,能够较好满足分布式并行编程的需求,适应大数据时代的到来. 函数是第一等公民 可以作为实参传递给另外一个函 ...

随机推荐

  1. Flutter防止布局溢出

    添加一层可滑动View(Widget)的布局, 将之前进行包裹: return new Scaffold(      appBar: new AppBar(        title: new Tex ...

  2. WEB前端常见受攻击方式及解决办法

    一个网站建立以后,如果不注意安全方面的问题,很容易被人攻击,下面就讨论一下几种漏洞情况和防止攻击的办法. 一.SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的 ...

  3. 深度搜索---------Lake counting

    #include<iostream>#include<cstdio>#include<cstdlib>#define maxn 100char ch[maxn][m ...

  4. Linux上搭建文件浏览的web服务(创建软件仓库)(一)

    软件仓库的创建方式有很多,这是一种很简单的创建方式: python -m SimpleHTTPServer 快速搭建一个http服务,提供一个文件浏览的web服务. 使用:Python SimpleH ...

  5. 学习MySQL这一篇就够了

    MySQL 第一章 数据库概述 1.1.数据库的好处 将数据持久化到本地 提供结构化查询功能 1.2.数据库的常见概念 DB:数据库,存储数据的仓库 DBS:数据库管理系统,又称为数据库软件或者数据库 ...

  6. 第五章 泛型&集合

    5.1.泛型 概述:泛型是是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数. 泛型类: // ...

  7. Numpy random函数

    import numpy as np # 生成一个随机数组 np.random.randint(0,6,3) # array([1, 1, 3]) # 生成一个随机数组(二维数组) np.random ...

  8. PHP xml_get_error_code() 函数

    定义和用法 xml_get_error_code() 函数获取 XML 解析器错误代码.高佣联盟 www.cgewang.com 如果成功,该函数则返回错误代码.如果失败,则返回 FALSE. 语法 ...

  9. MyBatis-Plus使用(3)-条件构造器

    说明: 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中 以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true 以下出现的泛型P ...

  10. day14.推导式与生成器

    一.列表推导式 '''通过一行循环判断,遍历一系列数据的方式''' """ 推导式的语法: val for val in Iterable 三种方式: [val for ...