隐式转换函数高级使用

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 = 1
    var num1:Int = 3.5   //double=>int
    var 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()   //huge
    test1     //zhou
    test()    //guo
    test      //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 User1
    user.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.5
      d.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+=6
    println(set1)           //Set(5, 1, 6, 2, 3, aa)
    var set2 = mutable.Set(1,2,3,"aa")//可变
    set2.add(5)
    set2.+=(6)
    set2+=8
    println(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)    //lizi
    println(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"))//存在:Some
    println(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值,不存在返回默认值     1
    println(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|6
    println(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|4
  print(ints1.mkString("|"))//1|2
  print(ints2.mkString("|"))//3
}

WordCount加强版:

def f6(): Unit ={
  //hello 14  world 7
  var 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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值