隐式转换函数高级使用
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)
隐式转换函数高级使用相关推荐
- C++定义隐式转换函数,将类转换为内部的一个成员变量
C++中单参数构造函数若不声明为explict,在合适的场合可以产生隐式转换:由成员变量类型转换为类类型. 下面的代码展示如何实现反向的转换: Code highlighting produced b ...
- C++转换构造函数和隐式转换函数
今天是第一次听到C++还有个转换构造函数,之前经常见到默认构造函数.拷贝构造函数.析构函数,但是从没听说过转换构造函数,隐式转换函数也是一样,C++的确是够博大精深的,再次叹服! 其实我们已经在C/C ...
- oracle隐式转换函数,隐式数据类型转换案例一则
在OLTP系统中,要求对频繁执行的SQL使用绑定变量(唯一值少的字段,如type.status等,数据分布不均是常见情况,这种字段不建议使用绑定变量). 在使用绑定变量时,有时开发人员对使用的字段类型 ...
- Spark记录-Scala程序例子(函数/List/match/option/泛型/隐式转换)
object func {def main(args:Array[String]):Unit={//函数赋值给变量时, 必须在函数后面加上空格和下划线.def sayHello(name: Strin ...
- Scala _09样例类(case classes)隐式转换
样例类(case classes) 概念理解 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类.实现了类构造参数的getter方法(构造参数默认被声明为val), ...
- scala中的隐式转换、隐式参数和隐式类
scala中的隐式转换.隐式参数和隐式类 @(SCALA)[scala] scala中的隐式转换隐式参数和隐式类 一隐式转换 1示例 2隐式转换的条件 二隐式参数 1示例 三隐式类 1示例 隐式转换是 ...
- Scala入门到精通——第十九节 隐式转换与隐式参数(二)
本节主要内容 隐式参数中的隐式转换 函数中隐式参数使用概要 隐式转换问题梳理 1. 隐式参数中的隐式转换 前一讲中,我们提到函数中如果存在隐式参数,在使用该函数的时候如果不给定对应的参数,则编译器会自 ...
- Scala入门到精通——第十八节 隐式转换与隐式参数(一)
本节主要内容 隐式转换简介 隐式转换函数 隐式转换规则 隐式参数 1. 隐式转换简介 在Scala语言当中,隐式转换是一项强大的程序语言功能,它不仅能够简化程序设计,也能够使程序具有很强的灵活性.要想 ...
- 深入理解Scala的隐式转换系统
原文链接:http://www.cnblogs.com/MOBIN/p/5351900.html ---------------------------------------------- 摘要: ...
最新文章
- Linux下通过txt文件导入数据到MySQL数据库
- xpath定位中starts-with、contains和text()的用法
- 【以太坊】ganache-cli和web3配合,操作以太坊客户端
- [PHP] 编写爬虫获取淘宝网上所有的商品分类以及关键属性 销售属性 非关键属性数据...
- java怎么用柱形图_java绘制柱形图
- 2+22+222+2222(直到n个2的精确计算)
- Blazor 中如何下载文件到浏览器
- flutter 国际化_Flutter 开发实战资源推荐
- 如何用SQLDMO在ASP.NET页面下实现数据库的备份与恢复
- Ubuntu18.04 LTS Melodic ROS 教程:使用URDF创建一个虚拟机器人模型
- android屏幕亮度测试,屏幕亮度与可视角度测试_手机Android频道-中关村在线
- 计算机二级office试题27答案,2017年12月计算机二级MS Office习题答案(一)
- 【练习8.7】cvGoodFeaturesToTrack确定图像强角点、cvFindCornerSubPix亚像素级角点检测...
- 如何在Mac上访问 USB 驱动器?
- snmptrap的使用方法
- 2019-CS224n-Assignment1
- 速达3000 数据库备份文件分析
- [转]供应链管理方面的书籍
- Ubuntu打开wps文件缺少字体
- 空间相册显示服务器错误,空间相册服务器繁忙
热门文章
- 大中型分布式系统中,Hystrix 分布式系统限流、降级、熔断框架
- sem新手实训课总结
- WEB应用防火墙安全技术要求与测试评价方法
- 单一世界架构初探之时间之轴
- 7-21 QQ帐户的申请与登陆
- [python爬虫]--调用有道词典进行翻译
- 【卡法 常用 ckl.js 库】: js汇合 表单验证 cookie设置 日期格式 电话手机号码 email 整数 小数 金额 检查参数长度...
- 一小时入门Python爬虫,连我都会了!Python爬取租房数据实例
- 建筑施工现场临时用电安全技术规范
- 大数据电信客服-数据采集/消费(二)