Scala隐式转换函数的底层原理

  • 类型不匹配:
    java:会强制转换
    scala:会使用对象的方法进行数据类型转换,隐式转换,scala中只看函数签名(参数列表和返回值)
object Scala_List3 {def main(args: Array[String]): Unit = {implicit  def f1(d:Double):Int={d.toInt}implicit  def f2(d:Long):Int={d.toInt}var num:Double = 1var num1:Int = 3.5   //double=>intvar num2:Int = 2001}
}
  • 补充:
    隐式转换函数的名字是任意的,隐式转换和函数名无关,和函数签名(参数列表–>返回值)有关。
    一个作用域内可以存在多个隐式函数,要保证当前环境能被识别的隐式函数只能有一个,不能有二义性。

隐式转换函数高级使用

需求:类Mysql------>insert 开发完之后发现缺少方法

  • 解决方法:

1.修改源码(重新修改mysql)

2.动态混入(OCP)

3.隐式转换(OCP)

object Scala_List3 {def main(args: Array[String]): Unit = {implicit def addDeletedMethod(mysql: Mysql): DBUtils ={new DBUtils}var mysql = new Mysql()mysql.insert()mysql.delete()}
}
class Mysql{def insert(): Unit = {println("删除数据。。。")}
}
class DBUtils{def delete(): Unit = {println("插入数据。。。")}
}

隐式转换函数:能帮助我们进行类型转换(隐式:无法直观看到数据类型)。

为什么要引入隐式转换:OCP(开闭原则)

为什么不直接修改源码:在任何一个程序里,类可能存在继承体系,如果直接修改源码的话,可能会给其他的类带来副作用

如果当前对象发现调用的方法不存在,那么会在作用域内进行搜索(隐式转换函数)、查询,看看是否有一个转换后的数据类型存在这个方法。

scala好处:编码简洁 缺点:源码难以理解

隐式值

案例一:

def main(args: Array[String]): Unit = {test1("lizi")     //lizi...test1()           //huge...test1             //huge...//函数形参用implicit修饰了,调用函数的时候可以不写小括号,默认用的就是隐式函数(形参)def test1(implicit name:String="huge"):Unit={println(name+"...")}}

案例二:

def main(args: Array[String]): Unit = {implicit var username1:String = "zhou" //隐式参数//函数形参用implicit修饰了,调用函数的时候可以不写小括号,默认用的就是隐式函数(形参)def test1(implicit name:String="huge"):Unit={println(name+"...")}def test(implicit name:String="guo"):Unit={println(name+"...")}test1()   //hugetest1     //zhoutest()    //guotest      //zhou}

如果当前调用的函数没有用implicit隐式转换关键字,就是调用方法,使用的就是形参

调用函数的时候,虽然使用了隐式转换关键词implicit修饰了形参,调用函数的时候使用了小括号,使用的就是自己的形参;调用函数的时候没有用小括号优先调用隐式参数,注意隐式参数要和形参类型一致,如果没有隐式参数就用自己的形参。

如果调用的函数,没有用implicit隐式转换关键词(关键字),就是调用方法、使用的是形参。

def main(args: Array[String]): Unit = {implicit var username1:String = "zhou"//函数形参用implicit修饰了,调用函数的时候可以不写小括号,默认用的就是隐式函数(形参)def test1(implicit name:String):Unit={println(name+"...")}test1("hh")   //hh...test1     //zhou}

隐式参数注释,test1会报错。

隐式类

案例一:

隐式类(特质、类(混入、继承)):扩展类功能

def main(args: Array[String]): Unit = {var user:User1 = new User1user.sayHello()user.printInfo()implicit class  NewUser(u:User1){//隐式类def printInfo(): Unit ={println("打印信息。。。")}}}
}
class User1{def sayHello(): Unit ={println("hello...")}

user1只有sayhello方法,没有其他方法,开发师不可能想的很全面,一定会进行程序的迭代(类:属性、方法修改、增加其他类和特质)

解决方案:1修改源码;2动态混入;3底层增加一个类(研发人员角度)、调用层(用户角度)、添加隐式函数;4用户层添加隐式类

注意:构造函数参数只能有一个;隐式类必须在类、伴生对象、包对象中,不能在顶级类中

补充说明: 隐式转换时机
1)函数中参数 和 调用不一样(触发参数)
2)对象调用的方法在自己的类中不存在(隐式函数、隐式类)

案例二:

  def main(args: Array[String]): Unit = {var user: User01 = new User01()user.sayHello()user.printInfo()user.name//隐式类中可以有属性implicit class NUser(u:User01){var name : String = "hello world"def printInfo(): Unit ={println("我在打印信息......")}}//隐式类}
}
class User01{def sayHello(): Unit ={println("user sayhello ......")}
}

案例三:隐式转换复杂操作

隐式转换机制(2种方案):
首先代码的作用域没查找隐式实体(隐式方法、隐式类、隐式对象)
如果第一条检索失败了、会继续查找、隐式参数类型的作用域(object内)开始查找

class A extends B with C(从左向右),常从伴生对象里找

 object Scala_List {def main(args: Array[String]): Unit = {var user: User01 = new User01()user.sayHello()user.printInfo()user.name//      implicit class Nuser(u:User01){//        var name : String = "hello world"//        def printInfo(): Unit ={//          println("我在打印信息......")//        }//      }}}
 class User01 extends T1{def sayHello(): Unit ={println("user sayhello ......")}}object User01{implicit class Nuser(u:User01){var name : String = "hello world"def printInfo(): Unit ={println("1......")println("我在打印信息......")}}}trait T1{//    implicit class Nuser(u:User01){//      var name : String = "hello world"//            def printInfo(): Unit ={//              println("我在打印信息......")//            }//          }//隐式类}object T1{implicit class Nuser(u:User01){var name : String = "hello world"def printInfo(): Unit ={println("0......")println("我在打印信息......")}}}

隐式转换最终注意事项

隐式转换前提:1.不能存在二义性 2.不能嵌套使用

def main(args: Array[String]): Unit = {//函数签名相同,出错implicit def f1(d:Double): Int ={var num:Int =3.5d.toInt}implicit def f2(d:Double): Int ={d.toInt}}

set、map

set不能存储重复元素,不能保留顺序、默认用的是哈希

默认情况下scala使用的是不可变集合,在scala里有可变的也有不可变的set

def main(args: Array[String]): Unit = {//不可变var set1 = Set(1,2,3)println(set1)//可变var set2 = mutable.Set(1,2,3)println(set2)}

案例:集合操作------添加数据

def main(args: Array[String]): Unit = {var set1 = Set(1,2,3,"aa")//不可变集合一般没有add这种方法set1.+=(5)set1+=6println(set1)           //Set(5, 1, 6, 2, 3, aa)var set2 = mutable.Set(1,2,3,"aa")//可变set2.add(5)set2.+=(6)set2+=8println(set2)           //Set(aa, 1, 5, 2, 6, 3, 8)}

案例:集合操作------删除数据

  def main(args: Array[String]): Unit = {var set1 = Set(1,2,3,"aa")val set:Set[Any]=set1.drop(2)println(set)  //Set(3, aa)var set2 = mutable.Set(1,2,3,"aa")set2.remove("aa")set2-=(3)println(set2)    //Set(1, 2)}

元组基本使用

元组可以理解为一个容器、这个容器可以存放不同的数据类型、可以承载很多元素数据、对数据没有过多的约束。

案例一:元组的基本使用

def main(args: Array[String]): Unit = {//tuple把无关的数据当成一个整体使用,构建元组最多22个值,但可以放list增加数据量val tuple1:Tuple4[String,Int,String,Boolean] = ("lizi",30,"xianggang",true)val tuple2:(String,Int,String,Boolean) = ("lizi",30,"xianggang",true)val tuple3:Tuple3[String,Int,String] = ("lizi",30,"xianggang")//访问元素println(tuple3._1)    //liziprintln(tuple3._2)    //30//遍历for(elem<-tuple3.productIterator){println(elem)              //lizi  30   xianggang}}

map

案例:scala:可变:无序 | 不可变:有序

def main(args: Array[String]): Unit = {//有序var map1 = Map("jiangjingwen"->40,"zhangting"->20,"linruiyang"->30)println(map1)   //Map(jiangjingwen -> 40, zhangting -> 20, linruiyang -> 30)//无序var map2 = mutable.Map("jiangjingwen"->40,"zhangting"->20,"linruiyang"->30)println(map2)   //Map(linruiyang -> 30, jiangjingwen -> 40, zhangting -> 20)}
def main(args: Array[String]): Unit = {var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))println(map("B"))   //2  //println(map("E")) //java里访问不存在的key会返回null,scala里访问不存在的key会报错//mutable.Map[String,Int]  //构建一个空的map }

案例:Map 增删改查

def f2(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))if (map.contains("E")){println("执行存在逻辑")}else{println("执行不存在逻辑")}}def f3(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))println(map.get("A"))//存在:Someprintln(map.get("R"))//不存在:None}def f4(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))println(map.getOrElse("A","默认值"))//如存在返回value值,不存在返回默认值     1println(map.getOrElse("X","默认值")) //默认值}def f5(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))map += ("F"->7)   //key不存在增加键值对  Map(D -> 4, A -> 1, C -> 3, F -> 7, B -> 2)println(map)map += ("C"->7)   //key存在会覆盖   Map(D -> 4, A -> 1, C -> 7, F -> 7, B -> 2)println(map)}def f6(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))var map2=map + ("G"->1,"H"->2) //返回的是新的对象println(map)    //Map(D -> 4, A -> 1, C -> 3, B -> 2)println(map2)   //Map(D -> 4, G -> 1, A -> 1, C -> 3, H -> 2, B -> 2)map += ("GG"->1,"HH"->2)println(map)    //Map(D -> 4, GG -> 1, A -> 1, C -> 3, HH -> 2, B -> 2)}def f7(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))map -= ("A","B")println(map)   //Map(D -> 4, C -> 3)}def f8(): Unit ={var map:mutable.Map[String,Int] = mutable.Map(("A",1),("B",2),("C",3),("D",4))//map.foreach(print)for(v<-map){      //java编程套路println(v+" ")}for((k,v)<-map){println(k+" "+v)}for (v<-map.keys){map.values}}

集合常用函数

集合基本方法

 var list = List(1,2,3,4)//求和println("sum = "+list.sum)//求最大值println("max = "+list.max)//求最小值println("min = "+list.min)//求乘积println("product = "+list.product)//反转println("reverse = "+list.reverse)

高阶出阶玩法

1.了解每个高阶函数功能

补充:确定的内容底层封装了(封装:什么内容需要底层实现,什么内容提交给用户实现),底层不确定的(行为参数化)

2.每个高级函数变化的东西是什么(需要用户层给高阶函数传递什么规则,才能让当前的高阶函数正常的执行)

高阶函数需要的函数(规则)----》输入的一般是当前集合的每个元素,但是返回值要特殊记忆一下

 def f2(): Unit ={var list = List(1,2,3,4)val inttoints:Map[Int,List[Int]] = list.groupBy(t=>t)inttoints.foreach(t=>print(t._1+"--"+t._2+":"))//2--List(2):4--List(4):1--List(1):3--List(3):}

按首字母分组:

 def f2(): Unit ={var list:List[String] = List("11","12","33","34")val chartostr:Map[Char,List[String]] = list.groupBy(e=>e.charAt(0))val strtostr:Map[String,List[String]] = list.groupBy(e=>e.substring(0,1))chartostr.foreach(t=>print(t._1+"--"+t._2))//1--List(11, 12)3--List(33, 34)strtostr.foreach(t=>print(t._1+"--"+t._2))//1--List(11, 12)3--List(33, 34)}

按奇偶数分组

  def f2(): Unit ={var list:List[Int] = List(1,2,3,4)val booleantoInT:Map[Boolean,List[Int]]=list.groupBy(i=>i%2==0)booleantoInT.foreach(t=>print(t._1+"--"+t._2))  //false--List(1, 3)true--List(2, 4)}

sortWith高阶函数(指定规则排序):

def f2(): Unit ={var list:List[Int] = List(5,6,1,2,3,4)//输入什么就按照什么排序var ints:List[Int] = list.sortBy(x=>x)println(ints.mkString("|"))//1|2|3|4|5|6println(ints.reverse.mkString("|"))//6|5|4|3|2|1//列表排序的:需要传递函数,输入列表中两个数值然后比较规则//输入的形参的两个值,左边小于右边是升序,左边大于右边是降序println(list.sortWith((x,y)=>x<y).mkString(","))//1,2,3,4,5,6//首字母排序var list1:List[String] = List("11","32","23","24")println(list1.sortWith((x,y)=>x.charAt(0)<y.charAt(0)).mkString(","))//11,23,24,32//查看中间过程list1.sortWith((x,y)=>{print(x+" "+y)x.charAt(0)<y.charAt(0)})//list迭代for(elem<-list.iterator){println(elem)//11322324}}

简易版本wordcount:

def f2(): Unit ={var list:List[Int] = List(1,2,3,4,4)var tuples:List[(Int,Int)] = list.map(x=>(x,1))//(1,1)|(2,1)|(3,1)|(4,1)|(4,1)println(tuples.mkString("|"))val intTotuples: Map[Int, List[(Int, Int)]] = tuples.groupBy(x=>x._1)println(intTotuples.mkString("|"))//2 -> List((2,1))|4 -> List((4,1), (4,1))|1 -> List((1,1))|3 -> List((3,1))//统计次数val intoint: Map[Int, Int]= intTotuples.map(t=>(t._1,t._2.size))println(intoint.mkString("|"))//2 -> 1|4 -> 2|1 -> 1|3 -> 1
}

单词出现次数最多的前3

def f2(): Unit ={var wordList = List("hello","xuchun","hello","hello","jinboran","sunyun","nini","jinboran","linyun","zhaoliyin","nini")//按单词分组val groupbyRDD: Map[String, List[String]] = wordList.groupBy(word=>word)//单词计数val mapRDD: Map[String, Int] = groupbyRDD.map(t=>(t._1,t._2.size))println(mapRDD.mkString("|"))val sortRDD:List[(String, Int)] = mapRDD.toList.sortWith((x,y)=>x._2>y._2)println(sortRDD.mkString("|"))val result: List[(String, Int)] = sortRDD.take(3)println(result.mkString("|"))
}

flatmap / fliter / zip 等函数的使用

  def f1(): Unit ={//flatmap  map关系var wordlist: List[String] = List("hello guanx","hello guant","hello guanz")//扁平化(数组里的值作为泛型)val faltMap: List[String] = wordlist.flatMap(x=>x.split(" "))val groupbyRDD: Map[String, List[String]]  =faltMap.groupBy(word=>word)groupbyRDD.map(t=>(t._1,t._2.size))//    println(faltMap.mkString("|"))//hello|guanx|hello|guant|hello|guanz
//    val str: List[Array[String]] = wordlist.map(x=>x.split(" "))
//    println(str.mkString("|"))
//[Ljava.lang.String;@880ec60|[Ljava.lang.String;@3f3afe78|[Ljava.lang.String;@7f63425a}
def f3(): Unit ={val list = List(1,2,3,4)val filterRDD: List[Int] = list.filter(x => false)filterRDD.foreach(t=>print(t))//没有输出val filterRDD1: List[Int] = list.filter(x => true)filterRDD1.foreach(t=>print(t))//1234
}
def f4(): Unit ={val list1 = List(1, 2, 3)val list2 = List(4, 5, 6,7)val tuple: List[(Int,Int)]=list1.zip(list2)//对位匹配print(tuple.mkString("|")) //(1,4)|(2,5)|(3,6)
}
def f5(): Unit ={val list1 = List(1, 2, 3)val list2 = List(1, 2, 4)val ints: List[Int] = list1.union(list2) //合并val ints1: List[Int] = list1.intersect(list2) //交集val ints2: List[Int] = list1.diff(list2)//差集print(ints.mkString("|"))//1|2|3|1|2|4print(ints1.mkString("|"))//1|2print(ints2.mkString("|"))//3
}

WordCount加强版:

def f6(): Unit ={//hello 14  world 7var linelist: List[(String, Int)] = List(("hello scala hello world",4),("hello world",3),("hello hadoop",2),("hello hbase",1))val flatmapRDD: List[(String,Int)] = linelist.flatMap(t=>{var line:String = t._1//"hello scala hello world"val word: Array[String] = line.split(" ")//"hello" "scala" "hello" "world"val mapRDD: Array[(String, Int)] = word.map(w=>(w,t._2))//("hello",4),("scala",4)....mapRDD})val groupRDD: Map[String, List[(String, Int)]] = flatmapRDD.groupBy(t=>t._1)val finalRDD: Map[String, Int] = groupRDD.map(t=>{val countlist: List[Int] = t._2.map(tt => tt._2)//List(4,3)(t._1,countlist.sum)})finalRDD.foreach(println)
}

输出:
(world,7)
(hadoop,2)
(scala,4)
(hello,14)
(hbase,1)

隐式转换函数高级使用相关推荐

  1. C++定义隐式转换函数,将类转换为内部的一个成员变量

    C++中单参数构造函数若不声明为explict,在合适的场合可以产生隐式转换:由成员变量类型转换为类类型. 下面的代码展示如何实现反向的转换: Code highlighting produced b ...

  2. C++转换构造函数和隐式转换函数

    今天是第一次听到C++还有个转换构造函数,之前经常见到默认构造函数.拷贝构造函数.析构函数,但是从没听说过转换构造函数,隐式转换函数也是一样,C++的确是够博大精深的,再次叹服! 其实我们已经在C/C ...

  3. oracle隐式转换函数,隐式数据类型转换案例一则

    在OLTP系统中,要求对频繁执行的SQL使用绑定变量(唯一值少的字段,如type.status等,数据分布不均是常见情况,这种字段不建议使用绑定变量). 在使用绑定变量时,有时开发人员对使用的字段类型 ...

  4. Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)

    object func {def main(args:Array[String]):Unit={//函数赋值给变量时, 必须在函数后面加上空格和下划线.def sayHello(name: Strin ...

  5. Scala _09样例类(case classes)隐式转换

    样例类(case classes) 概念理解 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类.实现了类构造参数的getter方法(构造参数默认被声明为val), ...

  6. scala中的隐式转换、隐式参数和隐式类

    scala中的隐式转换.隐式参数和隐式类 @(SCALA)[scala] scala中的隐式转换隐式参数和隐式类 一隐式转换 1示例 2隐式转换的条件 二隐式参数 1示例 三隐式类 1示例 隐式转换是 ...

  7. Scala入门到精通——第十九节 隐式转换与隐式参数(二)

    本节主要内容 隐式参数中的隐式转换 函数中隐式参数使用概要 隐式转换问题梳理 1. 隐式参数中的隐式转换 前一讲中,我们提到函数中如果存在隐式参数,在使用该函数的时候如果不给定对应的参数,则编译器会自 ...

  8. Scala入门到精通——第十八节 隐式转换与隐式参数(一)

    本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...

  9. 深入理解Scala的隐式转换系统

    原文链接:http://www.cnblogs.com/MOBIN/p/5351900.html ---------------------------------------------- 摘要: ...

最新文章

  1. Linux下通过txt文件导入数据到MySQL数据库
  2. xpath定位中starts-with、contains和text()的用法
  3. 【以太坊】ganache-cli和web3配合,操作以太坊客户端
  4. [PHP] 编写爬虫获取淘宝网上所有的商品分类以及关键属性 销售属性 非关键属性数据...
  5. java怎么用柱形图_java绘制柱形图
  6. 2+22+222+2222(直到n个2的精确计算)
  7. Blazor 中如何下载文件到浏览器
  8. flutter 国际化_Flutter 开发实战资源推荐
  9. 如何用SQLDMO在ASP.NET页面下实现数据库的备份与恢复
  10. Ubuntu18.04 LTS Melodic ROS 教程:使用URDF创建一个虚拟机器人模型
  11. android屏幕亮度测试,屏幕亮度与可视角度测试_手机Android频道-中关村在线
  12. 计算机二级office试题27答案,2017年12月计算机二级MS Office习题答案(一)
  13. 【练习8.7】cvGoodFeaturesToTrack确定图像强角点、cvFindCornerSubPix亚像素级角点检测...
  14. 如何在Mac上访问 USB 驱动器?
  15. snmptrap的使用方法
  16. 2019-CS224n-Assignment1
  17. 速达3000 数据库备份文件分析
  18. [转]供应链管理方面的书籍
  19. Ubuntu打开wps文件缺少字体
  20. 空间相册显示服务器错误,空间相册服务器繁忙

热门文章

  1. 大中型分布式系统中,Hystrix 分布式系统限流、降级、熔断框架
  2. sem新手实训课总结
  3. WEB应用防火墙安全技术要求与测试评价方法
  4. 单一世界架构初探之时间之轴
  5. 7-21 QQ帐户的申请与登陆
  6. [python爬虫]--调用有道词典进行翻译
  7. 【卡法 常用 ckl.js 库】: js汇合 表单验证 cookie设置 日期格式 电话手机号码 email 整数 小数 金额 检查参数长度...
  8. 一小时入门Python爬虫,连我都会了!Python爬取租房数据实例
  9. 建筑施工现场临时用电安全技术规范
  10. 大数据电信客服-数据采集/消费(二)