Scala高阶函数与泛型
1. Scala中的函数
在Scala中,函数是“头等公民”,就和数字一样。可以在变量中存放函数,即:将函数作为变量的值(值函数)。
2. scala中的匿名函数,即没有函数名称的函数,匿名函数常作为高阶函数的参数使用
(x: Int) => x*3
=>使用场景小结:
a. 用于匿名函数中连接函数声明和函数体
b. 用于模式匹配中,连接case条件和表达式 case "+" => "This is a positive number"
c. 用于函数参数中,表示Call By Name的求值策略,函数实参每次在函数体内被用到时都会求值
3. scala中高阶函数分析
高阶函数:把函数作为参数的函数
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中常用的高阶函数
scala> val numbers = List(1,2,3,4,5,6,7,8,9)
numbers: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> numbers.map(_*2)
res20: List[Int] = List(2, 4, 6, 8, 10, 12, 14, 16, 18) scala> numbers.foreach(_*2) scala> numbers
res22: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) *******由此结果可知,map操作返回一个新的list,foreach操作只有过程无返回值 scala> numbers.filter(_%2==0)
res23: List[Int] = List(2, 4, 6, 8) List(1,3,7).zip(List(2,4,6))
res30: List[(Int, Int)] = List((1,2), (3,4), (7,6)) 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))
res30: List[(Int, Int)] = List((1,2), (3,4), (7,6)) scala> numbers.find(_%3==0)
res31: Option[Int] = Some(3) 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)) scala> myList.flatten
res32: List[Int] = List(1, 5, 7, 3, 2, 6)
flatMap与map的区别比较明显,map针对单个元素进行操作,对于嵌套的集合类型操作完成后不会压平。
scala> val li = List(1,2,3)
li: List[Int] = List(1, 2, 3) scala> val res = li.flatMap(x => x match {
| case 3 => List('a','b')
| case _ => List(x*2)
| })
res: List[AnyVal] = List(2, 4, a, b) scala> li.map(x => x match {
| case 3 => List('a','b')
| case _ => x*2
| })
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)
scala> val bag = List("1", "2", "three", "4", "one hundred seventy five")
bag: List[String] = List(1, 2, three, 4, one hundred seventy five) scala> def toInt(in: String): Option[Int] = {
| try {
| Some(Integer.parseInt(in.trim))
| } catch {
| case e: Exception => None
| }
| }
toInt: (in: String)Option[Int] scala> bag.map(toInt)
res46: List[Option[Int]] = List(Some(1), Some(2), None, Some(4), None)
8. scala中的泛型
a.泛型类
b. 泛型函数
注意:这里的ClassTag是必须的,表示运行时的一些信息,比如类型。
scala> import scala.reflect.ClassTag
import scala.reflect.ClassTag scala> def mkArray[T: ClassTag](elems:T*) = Array[T](elems:_*)
mkArray: [T](elems: T*)(implicit evidence$1: scala.reflect.ClassTag[T])Array[T] scala> mkArray(1,2,3,4,5)
res47: Array[Int] = Array(1, 2, 3, 4, 5)
c.Upper Bounds 与 Lower Bounds
类型的上界和下界,是用来定义类型变量的范围。它们的含义如下:
S <: T 这是类型上界的定义。也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类。
U >: T 这是类型下界的定义。也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。
* 演示类型变量的上界: S <: T
* S和T代表类型
* 含义是:S必须是T的子类或者本事,则T就叫S的上界
*/ //定义父类:Vehicle代表所有的交通工具
class Vehicle{
//方法:驾驶
def drive() ={println("Driving")}
} //定义Vehicle的两个子类:Car和Bicycle
class Car extends Vehicle{
override def drive() ={println("Car Driving")}
}
class Bicycle extends Vehicle{
override def drive() ={println("Bicycle Driving")}
}
//测试
object ScalaUpperBounds {
//定义方法
def takeVehicle[T <: Vehicle](v:T) = {v.drive()} def main(args: Array[String]) {
//定义一个交通工具的对象
var v:Vehicle = new Vehicle
takeVehicle(v) var c:Car = new Car
takeVehicle(c)
}
}
d. 视图界定(View bounds)
尽量使用视图界定,来取代泛型的上界,因为适用的范围更加广泛。视图界定<% 除了所有的子类型,还允许隐式转换过去的类型。
隐式转换是指采用implicit关键字修饰的类函数和属性,它在定义完成后由scala在后台自动运行,当遇到匹配的转换类型,scala会自动完成隐式转换。
//Scala的隐式转换 //水果
class Fruit(name:String){
def getFruitName():String = {name}
} //猴子Monkey
class Monkey(f:Fruit){
def say() = {println("Monkey like " + f.getFruitName())}
} object ImplicitDemo {
implicit def fruitToMonkey(f:Fruit):Monkey = {new Monkey(f)} def main(args: Array[String]) {
//创建一个Fruit的对象
var f:Fruit = new Fruit("香蕉")
//问题:能否调用f.say() 方法呢?解决方法:将Fruit的对象转换为Monkey的对象
f.say()
}
}
e:协变与逆变
协变:Scala的类或特征的范型定义中,如果在类型参数前面加入+符号,就可以使类或特征变为协变了。泛型变量的值可以是本身类型或者其子类的类型
逆变:在类或特征的定义中,在类型参数之前加上一个-符号,就可定义逆变范型类和特征了。泛型变量的值可以是本身类型或者其父类的类型
//Scala的逆变:泛型变量的值可以是本身或者其父类 package demo2{
//父类:动物
class Animal{}
//子类:鸟
class Bird extends Animal
//麻雀
class Sparrow extends Bird //吃东西的类
class EatSomething[-T](t:T){} object DemoClass2 {
def main(args: Array[String]) {
//创建一个Bird吃东西的对象
var c1:EatSomething[Bird] = new EatSomething[Bird](new Bird) //创建一个麻雀吃东西的对象
//问题:能否将c1付给c2?
//原因:尽管Bird是Sparrow的父类,但是EatSomething[Bird]不是EatSomething[Sparrow]的父类
var c2:EatSomething[Sparrow] = c1
}
}
}
Scala高阶函数与泛型的更多相关文章
- scala高阶函数类型推断什么时候失效?
class TypeInfer(self: Int, other: Int) { def test(num: Int, word: String, fun1: (Int, Int) => Int ...
- Scala高阶函数
1.作为参数的函数 函数可以作为一个参数传入到一个方法当中去 def main(args: Array[String]): Unit = { val myFunc1 =(x:Int) =>{ x ...
- Scala高阶函数实践
高阶函数主要有两种:一种是将一个函数当做另外一个函数的参数(即函数参数):另外一种是返回值是函数的函数.package sparkCore/** * Created by zhen on 2018/3 ...
- Scala高阶函数示例
object Closure { def function1(n: Int): Int = { val multiplier = (i: Int, m: Int) => i * m multip ...
- scala面向对象.高阶函数,柯里化,Actor编程简介
1.定义一个类 class Person{ //用val修饰的变量是只读属性,有getter但是没有setter val id ="111" //用var修饰的变量既有getter ...
- Scala 基础(十一):Scala 函数式编程(三)高级(一)偏函数、作为参数的函数、匿名函数、高阶函数
1 偏函数 1)在对符合某个条件,而不是所有情况进行逻辑操作时,使用偏函数是一个不错的选择 2)将包在大括号内的一组case语句封装为函数,我们称之为偏函数,它只对会作用于指定类型的参数或指定范围值的 ...
- Scala集合操作中的几种高阶函数
Scala是函数式编程,这点在集合操作中大量体现.高阶函数,也就是能够接收另外一个函数作为参数的函数. 假如现在有一个需要是将List集合中的每个元素变为原来的两倍,现在来对比Java方式实现和Sca ...
- Scala中的构造器和高阶函数
构造器 在定义类时可以定义主构造器.主构造器可以同时声明字段. /** * 主构造器 * @author Administrator */ //在scala中,类和方法交织在一起 class Test ...
- Thinking in scala (6)----高阶函数----返回一个函数
在Thinking in scala (5)----高阶函数* 里面,我们演示了如何把一个函数作为参数传递给另外一个函数. 在本文里面,我们来演示函数式编程另外一个重要的特性:返回一个函数.首先来看这 ...
随机推荐
- 按下F2编辑dxDBTreeView的节点
在TdxDBTreeView控件的OnKeyDown事件中写入if Key = VK_F2 thenbegin if DBTreeMain.DBSelected = nil then Exit ...
- mysql一条语句实现插入或更新的操作
,),(,) ON DUPLICATE KEY UPDATE c=VALUES(c); 或者 INSERT INTO table (id,a,b,c) select id,a,b,c from xxx ...
- 三小时攻克 Kubernetes!
我保证本文是最详尽的 Kubernetes 技术文档,从我在后台排版了这么漫长的时间就能看出来.废话不多说——牢牢占据容器技术统治地位的 Kubernetes,其重要性想必不言而喻. 以下为译文: 为 ...
- css解决fixed布局不会出现滚动条问题
需求是页面移动到一定高度时,顶部出现固定的导航栏,并导航栏带滚动条. CSS很好实现,但是导航栏飘浮顶部后,滚动条怎么也不显示,搜了一些资料终于解决了,现做下笔记. <div class=&qu ...
- selenium+python自动化框架
流程: 环境准备 eclipse :需安装pydev.testng插件 python :安装python完成后,需 pip下安装selenium:命令: pip install selenium 我现 ...
- python-Web-flask-蓝图和单元测试
4 蓝图和单元测试: 能够使用代码实现蓝图对项目进行模块化 admin=Blueprint('admin',__name__) # 创建一个蓝图对象 @admin.route('/') def adm ...
- Go语言实现bitmap算法
有关bitmap算法的介绍资料网上很多,这里不赘述,各种语言的实现也不少,但是Go语言版的bitmap不多,本文就来写一个Go版的bitmap实现. 首先创建一个 bitmap.go 文件,定义一个b ...
- 【MOOC课程学习记录】程序设计与算法(一)C语言程序设计
课程结课了,把做的习题都记录一下,告诉自己多少学了点东西,也能给自己一点鼓励. ps:题目都在cxsjsxmooc.openjudge.cn上能看到,参考答案在差不多结课的时候也会在mooc上放出来. ...
- 最新 顺网科技java校招面经 (含整理过的面试题大全)
从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.顺网科技得等10家互联网公司的校招Offer,因为某些自身原因最终选择了顺网科技.6.7月主要是做系统复习.项目复盘.Lee ...
- 文件input框选择图片实时显示小技巧
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...