scala的偏函数
PartialFunction中文翻译结果是部分功能,partial是部分的,偏袒的意思
什么是偏函数?
就是局部函数,也就是再处理内容的时候,对总内容的部分内容进行处理,将结果返回到一个新的容器中
上代码
//scala偏函数
//什么是偏函数?偏函数说白了就是局部函数,再通俗一点就是对一部分数据应用函数,
// 也就是再调用 函数的时候增加了判断条件,增加了过滤元素的功能
//实现对list中数字加一的功能,这种对部分数据进行处理的时候我们就可以使用偏函数
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4,5,"Hello")
val partialFunction=new PartialFunction[Any,Int] {
//确定过滤条件
override def isDefinedAt(x: Any): Boolean = {
x.isInstanceOf[Int]
}
//确定执行内容
override def apply(v1: Any): Int = {
v1.asInstanceOf[Int]+1
}
}
println(list.collect(partialFunction).toBuffer)//ArrayBuffer(2, 3, 4, 5, 6)
}
要使用collect方法应用偏函数,map方法对每个对象都遍历,是不支持偏函数的
简易写法
val list2 = List(1,2.3,3,4.1,5,"Hello")
//定义一个函数,无参,返回值是一个偏函数,利用了模式匹配,当int类型的时候+1,当double的时候乘2后转为int
def partialFun2 :PartialFunction[Any,Int]={
case i:Int=>i+1
case x:Double=>(x*2).toInt
}
println(list2.collect(partialFun2).toBuffer)//ArrayBuffer(2, 4, 4, 8, 6)
更简易的写法
主要使用了匿名函数加上模式匹配
{case a,case b,case d}是一个匿名偏函数,其中case匹配不同的类型,进行不同的处理
val list2 = List(1,2.3,3,4.1,5,"Hello")
println(list2.collect(
{
case a: Int => a + 1
case b: Double => (b * 2).toInt
case d: String => 1000
}
).toBuffer)//ArrayBuffer(2, 4, 4, 8, 6, 1000)
函数作为返回值和参数
Scala的函数作为参数和返回值,以及Scala的方法作为参数和返回值的内容在上一篇文章中也进行了详细的介绍,有需要的同学可以一览
附上链接
为什么scala中的函数可以像值一样传递?因为函数是引用类型,是FunctionN的实例
_可以将方法转换为方法的引用
例如集合中的map,reuduce等都是接收函数变量的
可以查看
函数可以用{}包裹,不仅仅是()
函数的完整定义
val 函数名:函数类型(函数参数=>返回值)=(参数列表)=>(返回值){}因为可以自动推断类型,所以
val 函数名=(参数列表:参数类型)=>{方法体}
返回值是可以自动推断的,函数类型也是可以自动推断的,这里的函数返回一个函数,也可以看作是返回了函数的引用
Scala的匿名函数
匿名函数也就是没有名字的函数,跟Java中的一样,可以减少取名字的挣扎,这类函数通常使用一次,因为没有变量引用
强调Scala中函数和方法不一样,点击上面的链接有详细介绍
val list3 = List(1.3,2.3,3.34,4.1,5.1)
//比如定义一个匿名函数,用一个变量接收,这时候在需要使用的地方就可以直接将变量当作参数传进去
val func1=(a :Double)=>{(a*a).toInt}
println(list3.map(func1).toBuffer)//ArrayBuffer(1, 5, 11, 16, 26)
Scala高阶函数
什么是高阶函数?就是能够接收函数作为参数的函数,就称之为高阶函数,预留出具体的业务处理实现给调用者
//定义一个高阶函数 val functionHigt=(a:Int,f:Int=>Int)=>{f(a)} 解释一下这句话,这里定义了一个变量接收函数functionHigt ()的内容是函数的类型,注意函数的类型是(参数列表)+返回值,由于具备类型推断,所有不用指定返回值也可以 =>代表这是一个函数,{}是函数体 其中的f:Int=>Int,指明了一个函数类型,这个函数的类型是输入一个Int,返回一个Int的函数类型 {f(a)}是对输入进来的a应用f函数,而这个函数还没有定义,所以我们可以在,调用函数的时候指定具体的处理逻辑functionHigt(12,a=>a*12)直接调用,调用的时候传进去数值,然后传进去匿名函数
而将函数作为返回值,这只是将函数转化为方法的办法,通过定义一个方法,内部调用具体函数
闭包
就是找到同一地址中父级函数的局部变量的最终值
柯里化方法
,可以将原本是多个参数(a,b,c,d)的方法,_转换成函数,然后通过func(a)_传入第一个参数,
形成func(a)(b)(c)的形式,闭包函数就是柯里化函数,所以闭包可以使用父函数的变量
就是将一个原本需要多个参数的函数转换为每次需要一个参数的函数的过程.新的函数返回以第一个函数为参数的函数
隐式参数
也就是用implicit修饰的参数,表明这个参数是可选的,可以在参数列表定义时给默认值,
如果没有给默认值,会去上下文中找相同类型的implicit修饰的参数,
优先级别是 : 默认值<上下文<自己传入
隐式参数只能定义在第一个,可以放到object和class(需要new)中保存隐式参数,
普通的函数也可以用implicit修饰
隐式函数通常和柯里化构成可选参数
隐式转换
隐式转换函数:也就是用implicit修饰的单个参数的函数,这样的函数将会被自动执行(要导入),
隐式转换是为了扩展和增强类而出现的
隐式转换实际上就是装饰者模式+门面模式
通常都是用来扩展一个现有类的方法,将现有类转换为更丰富的类,在实际代码前面使用import的方法,来导入隐式转换
当运行到该行后会自动使用implicit修饰的方法和变量(具体参考前面的隐式函数),完成对象的转变
将一个类型转换为另一个类型
例子一,将Double隐式转换为Int
object BeanToBean {
//在本作用域直接定义会自动导入
def main(args: Array[String]): Unit = {
//直接定义会报错
//定义一个隐式转换
val num:Int=12.5
println(num)
val num2:Double=12
}
implicit def changeInt(x:Double):Int={x.toInt}
}
Int类型为什么可以保存到Double中?就是因为scala在PreDef中将Int隐式转化为Double了(int2Double为其方法名)
自动呼出隐式方法,将原本的类型转换为函数中定义的类型
隐式转换的方法返回值和参数必须一致
隐式转换可以从当前类中(但是要new)获取,也可以从伴生对象中获取(直接导入就可以使用)
import object名字.{methodName=>_,_} 排除隐式转换
package com.implicitS
import java.io.File
object RichDemo {
def main(args: Array[String]): Unit = {
import com.implicitS.RichFile._
//导入隐式转换
val file: File = new File("K:\\word.txt")
println(file.read())
}
}
import java.io.File
import scala.io.Source
class RichFile(file:File) {
//定义一个方法
def read():String={
Source.fromFile(file).mkString
}
}
object RichFile{
//隐式函数将这个类转换为richfile类,会自动呼出转换方法,只要是File类,就会都进行转换
implicit val chengeBean=(filebean:File)=>{new RichFile(filebean)}
}
视图转换
class Boy[T <% Ordered[T]] {
//这里的传进来的类可以没有>=等比较方法
def choose(first: T,second: T): T = {
if(first >= second) first else second
}
}
object Boy{
def main(args: Array[String]): Unit = {
import Context.userToOrderedUser
val unit = new Boy[User]
val user: User = new User("b",12)
val user2: User = new User("a",14)
println(unit.choose(user, user2))
}
}
//公共域中定义隐式转换规则
object Context{
//注意此处声明返回值,要不然会出异常
implicit def userToOrderedUser(user:User):Ordered[User]=new Ordered[User] {
override def compare(that: User): Int = that.fv-user.fv
}
}
上下文界定
package com.relation
class Info[T:Ordering] {
//定义一个扩展类,这个类的泛型是Ordering的
def bigger(first: T,last:T):T={
//指定使用静态转换
val value: Ordering[T] = implicitly[Ordering[T]]
//返回的是
if (value.gteq(first,last)) first else last
}
}
object Test{
def main(args: Array[String]): Unit = {
import Test.OrderingUser
//导入隐式转换
val unit: Info[User] = new Info[User]
val user: User = new User("tom",12)
val user2: User = new User("tom",14)
val result = unit.bigger(user,user2)
println(result.fv+"----"+result.id)
}
implicit object OrderingUser extends Ordering[User]{
override def compare(x: User, y: User): Int = x.fv-y.fv
}
}
上下文界定的时候需要返回类型
视图界定和隐式转换需要返回将类型进行转换的方法
* 视图界定:隐式转换函数或方法
* 下文界定:隐射转换类型(参数)
不使用上下文和视图