1. Scala中的函数

在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)

2. scala中的匿名函数,即没有函数名称的函数,匿名函数常作为高阶函数的参数使用

(x: Int) => x*3

  =>使用场景小结:

  a. 用于匿名函数中连接函数声明和函数体

  b. 用于模式匹配中,连接case条件和表达式  case "+" => "This is a positive number"

  c. 用于函数参数中,表示Call By Name的求值策略,函数实参每次在函数体内被用到时都会求值

3. scala中高阶函数分析

  高阶函数:把函数作为参数的函数

  1. def hFunc(f: (Double) => (Double)) = f(10)
    //f:为一个参数为Double,返回值也是Double的函数,作为高阶函数hFunc的参数,可以简单将f理解为函数名称的占位符,定义一个具体函数后将其替换; 

  scala> def half(x: Double):Double = x / 2
  half: (x: Double)Double

  scala> def hFunc(f: (Double) => (Double)) = f(10)
  hFunc: (f: Double => Double)Double

  scala> hFunc(half)
  res19: Double = 5.0

  //上述运行过程可看成   hFunc(half) = half(10)

4. 闭包:可理解为函数的嵌套

在一个函数定义中,包含另外一个函数的定义;并且在内函数中可以访问外函数中的变量。

5. 柯里化:

柯里化函数(Curried Function)是把具有多个参数的函数转换为一条函数链,每个节点上是单一参数。

6. scala中常用的高阶函数

  1. scala> val numbers = List(1,2,3,4,5,6,7,8,9)
  2. numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)      
  3. scala> numbers.map(_*2)
  4. res20: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18)
  5.  
  6. scala> numbers.foreach(_*2)
  7.  
  8. scala> numbers
  9. res22: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)    *******由此结果可知,map操作返回一个新的listforeach操作只有过程无返回值 
  10.  
  11. scala> numbers.filter(_%2==0)
    res23: List[Int] = List(2, 4, 6, 8)
  12.  
  13. List(1,3,7).zip(List(2,4,6))
    res30: List[(Int, Int)] = List((1,2), (3,4), (7,6))
  14.  
  15. scala> numbers.partition((i:Int) => i%3==0||i%3==1)
    res29: (List[Int], List[Int]) = (List(1, 3, 4, 6, 7, 9),List(2, 5, 8))scala> List(1,3,7).zip(List(2,4,6))
  1. res30: List[(Int, Int)] = List((1,2), (3,4), (7,6))
  2.  
  3. scala> numbers.find(_%3==0)
    res31: Option[Int] = Some(3)
  4.  
  5. scala> val myList = List(List(1,5,7),List(3,2,6))
    myList: List[List[Int]] = List(List(1, 5, 7), List(3, 2, 6))
  6.  
  7. scala> myList.flatten
    res32: List[Int] = List(1, 5, 7, 3, 2, 6)  

flatMap与map的区别比较明显,map针对单个元素进行操作,对于嵌套的集合类型操作完成后不会压平。

  1. scala> val li = List(1,2,3)
  2. li: List[Int] = List(1, 2, 3)
  3.  
  4. scala> val res = li.flatMap(x => x match {
  5. | case 3 => List('a','b')
  6. | case _ => List(x*2)
  7. | })
  8. res: List[AnyVal] = List(2, 4, a, b)
  9.  
  10. scala> li.map(x => x match {
  11. | case 3 => List('a','b')
  12. | case _ => x*2
  13. | })
  14. res44: List[Any] = List(2, 4, List(a, b))

7. scala中的Option

Option[T]

在Scala里Option[T]实际上是一个容器,就像数组或是List一样,你可以把他看成是一个可能有零到一个元素的List。
当你的Option里面有东西的时候,这个List的长度是1(也就是 Some),而当你的Option里没有东西的时候,它的长度是0(也就是 None)

  1. scala> val bag = List("1", "2", "three", "4", "one hundred seventy five")
  2. bag: List[String] = List(1, 2, three, 4, one hundred seventy five)
  3.  
  4. scala> def toInt(in: String): Option[Int] = {
  5. | try {
  6. | Some(Integer.parseInt(in.trim))
  7. | } catch {
  8. | case e: Exception => None
  9. | }
  10. | }
  11. toInt: (in: String)Option[Int]
  12.  
  13. scala> bag.map(toInt)
  14. res46: List[Option[Int]] = List(Some(1), Some(2), None, Some(4), None)

8. scala中的泛型

  a.泛型类

  

  b. 泛型函数  

注意:这里的ClassTag是必须的,表示运行时的一些信息,比如类型。

  1. scala> import scala.reflect.ClassTag
  2. import scala.reflect.ClassTag
  3.  
  4. scala> def mkArray[T: ClassTag](elems:T*) = Array[T](elems:_*)
  5. mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T]
  6.  
  7. scala> mkArray(1,2,3,4,5)
  8. res47: Array[Int] = Array(1, 2, 3, 4, 5)

  c.Upper Bounds 与 Lower Bounds

  类型的上界和下界,是用来定义类型变量的范围。它们的含义如下:

  S <: T  这是类型上界的定义。也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类。

U >: T  这是类型下界的定义。也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。

  1. * 演示类型变量的上界: S <: T
  2. * ST代表类型
  3. * 含义是:S必须是T的子类或者本事,则T就叫S的上界
  4. */
  5.  
  6. //定义父类:Vehicle代表所有的交通工具
  7. class Vehicle{
  8. //方法:驾驶
  9. def drive() ={println("Driving")}
  10. }
  11.  
  12. //定义Vehicle的两个子类:Car和Bicycle
  13. class Car extends Vehicle{
  14. override def drive() ={println("Car Driving")}
  15. }
  16. class Bicycle extends Vehicle{
  17. override def drive() ={println("Bicycle Driving")}
  18. }
  1. //测试
  2. object ScalaUpperBounds {
  3. //定义方法
  4. def takeVehicle[T <: Vehicle](v:T) = {v.drive()}
  5.  
  6. def main(args: Array[String]) {
  7. //定义一个交通工具的对象
  8. var v:Vehicle = new Vehicle
  9. takeVehicle(v)
  10.  
  11. var c:Car = new Car
  12. takeVehicle(c)
  13. }
  14. }

  d. 视图界定(View bounds) 

  尽量使用视图界定,来取代泛型的上界,因为适用的范围更加广泛。视图界定<% 除了所有的子类型,还允许隐式转换过去的类型。

  隐式转换是指采用implicit关键字修饰的类函数和属性,它在定义完成后由scala在后台自动运行,当遇到匹配的转换类型,scala会自动完成隐式转换。

  

  1. //Scala的隐式转换
  2.  
  3. //水果
  4. class Fruit(name:String){
  5. def getFruitName():String = {name}
  6. }
  7.  
  8. //猴子Monkey
  9. class Monkey(f:Fruit){
  10. def say() = {println("Monkey like " + f.getFruitName())}
  11. }
  12.  
  13. object ImplicitDemo {
  14. implicit def fruitToMonkey(f:Fruit):Monkey = {new Monkey(f)}
  15.  
  16. def main(args: Array[String]) {
  17. //创建一个Fruit的对象
  18. var f:Fruit = new Fruit("香蕉")
  19. //问题:能否调用f.say() 方法呢?解决方法:将Fruit的对象转换为Monkey的对象
  20. f.say()
  21. }
  22. }

  e:协变与逆变  

  协变:Scala的类或特征的范型定义中,如果在类型参数前面加入+符号,就可以使类或特征变为协变了。泛型变量的值可以是本身类型或者其子类的类型

  逆变:在类或特征的定义中,在类型参数之前加上一个-符号,就可定义逆变范型类和特征了。泛型变量的值可以是本身类型或者其父类的类型

  

  1. //Scala的逆变:泛型变量的值可以是本身或者其父类
  2.  
  3. package demo2{
  4. //父类:动物
  5. class Animal{}
  6. //子类:鸟
  7. class Bird extends Animal
  8. //麻雀
  9. class Sparrow extends Bird
  10.  
  11. //吃东西的类
  12. class EatSomething[-T](t:T){}
  13.  
  14. object DemoClass2 {
  15. def main(args: Array[String]) {
  16. //创建一个Bird吃东西的对象
  17. var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird)
  18.  
  19. //创建一个麻雀吃东西的对象
  20. //问题:能否将c1付给c2?
  21. //原因:尽管Bird是Sparrow的父类,但是EatSomething[Bird]不是EatSomething[Sparrow]的父类
  22. var c2:EatSomething[Sparrow] = c1
  23. }
  24. }
  25. }

Scala高阶函数与泛型的更多相关文章

  1. scala高阶函数类型推断什么时候失效?

    class TypeInfer(self: Int, other: Int) { def test(num: Int, word: String, fun1: (Int, Int) => Int ...

  2. Scala高阶函数

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

  3. Scala高阶函数实践

    高阶函数主要有两种:一种是将一个函数当做另外一个函数的参数(即函数参数):另外一种是返回值是函数的函数.package sparkCore/** * Created by zhen on 2018/3 ...

  4. Scala高阶函数示例

    object Closure { def function1(n: Int): Int = { val multiplier = (i: Int, m: Int) => i * m multip ...

  5. scala面向对象.高阶函数,柯里化,Actor编程简介

    1.定义一个类 class Person{ //用val修饰的变量是只读属性,有getter但是没有setter val id ="111" //用var修饰的变量既有getter ...

  6. Scala 基础(十一):Scala 函数式编程(三)高级(一)偏函数、作为参数的函数、匿名函数、高阶函数

    1 偏函数 1)在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择 2)将包在大括号内的一组case语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范围值的 ...

  7. Scala集合操作中的几种高阶函数

    Scala是函数式编程,这点在集合操作中大量体现.高阶函数,也就是能够接收另外一个函数作为参数的函数. 假如现在有一个需要是将List集合中的每个元素变为原来的两倍,现在来对比Java方式实现和Sca ...

  8. Scala中的构造器和高阶函数

    构造器 在定义类时可以定义主构造器.主构造器可以同时声明字段. /** * 主构造器 * @author Administrator */ //在scala中,类和方法交织在一起 class Test ...

  9. Thinking in scala (6)----高阶函数----返回一个函数

    在Thinking in scala (5)----高阶函数* 里面,我们演示了如何把一个函数作为参数传递给另外一个函数. 在本文里面,我们来演示函数式编程另外一个重要的特性:返回一个函数.首先来看这 ...

随机推荐

  1. JAVA 基础编程练习题43 【程序 43 求奇数个数】

    43 [程序 43 求奇数个数] 题目:求 0—7 所能组成的奇数个数. package cskaoyan; public class cskaoyan43 { @org.junit.Test pub ...

  2. PhpStorm设置项目编码

    因为工作中论坛项目用的是GBK编码.数据库也是GBK编码.模板也是GBK,所以为了以后修改程序不出现乱码问题,所以需要把我的PhpStorm中该项目也设置为GBK编码(默认是UTF8编码). 设置路径 ...

  3. Flutter Widget框架概述

    Flutter Widget采用现代响应式框架构建,这是从 React 中获得的灵感,中心思想是用widget构建你的UI. Widget描述了他们的视图在给定其当前配置和状态时应该看起来像什么.当w ...

  4. Allegro静态铜皮避让问题

    使用Allegro的人都知道,Allegro的铜分为静态和动态,我的设计习惯是需要满足载流地方一般使用静态铜皮,避免设计过程中因为打孔把铜皮割裂,这是静态铜皮的一个特性,不会自动避让,强制打孔或者走线 ...

  5. 差分约束算法————洛谷P4878 [USACO05DEC] 布局

    题目: 不难看出题意主要是给出ml+md个格式为xi-xj<=ak的不等式,xi-xj为i,j俩头牛的距离,要我们求x1-xn的最大值. 经过上下加减我们可以将这几个不等式化成x1-xn< ...

  6. Insomni’hack CTF-l33t-hoster复现分析

    题目地址: https://github.com/eboda/insomnihack/tree/master/l33t_hoster 源码如下: <?php if (isset($_GET[&q ...

  7. 【FFMPEG】【ARM-Linux开发】 ffmpeg 静态库使用,undefined reference错误

    原文:http://blog.csdn.net/chinazjn/article/details/7954984 ffmpeg移植到dm365上,遇到undefined reference错误: GA ...

  8. centOS 安装 pm2

    安装 npm install -g pm2 自启 pm2 startup centos 启动 pm2 start server/add.js (以实际路径为准) 其他命令: pm2 list #查看进 ...

  9. vue项目中的父子组件之间的传值。

    首先说一下父子组件就是在一个vue文件中引入另一个vue文件,被引入vue文件就是子组件,引入vue文件的vue文件就是父组件.而在父组件中是不能直接调用子组件中的变量值的.下面详细说一下,父子组件之 ...

  10. 洛谷 题解 P1220 【关路灯 】

    搜索 传参 inline void DFS(int now,int l,int r,int cnt,int sum,int k) /* now为当前点 l为左端点 r为右端点 cnt为当前耗电量 su ...