zoukankan      html  css  js  c++  java
  • scala与java之间的那些事

      scala与java之间的关系,我认为可以用一句话来开头:scala来源于java,但又高于java。

      scala的设计者Martin Odersky就是一个JAVA控,这位牛人设计了javac和编写了jdk中的通用代码。可以说java语言本身就是Martin Odersky一步一步看着长大的。所以scala可以说打根起就和JAVA有着远远悠长的血缘关系。

      Martin Odersky还在写java那会,就立志开发达成一个目标:让写程序这样一个基础工作变得高效、简单、且令人愉悦!因此可以说scala是这个目标实现过程中的一个重要里程碑。

      因此可以说java是职业装,scala就是休闲服。

      scala简练,高效。java成熟,稳重。

      但是尺有所长,寸有所短。scala的简练高效有其独有的使用范围:scala最适合用在算法描述领域,java适合用在指令编程领域。

    scala独有的两招:函数式编程、简单的并发编程.

    1、scala独有的函数式编程。

      函数是scala语言中的一等公民。

      一等公民的特权表现在:1.函数可以传递、赋值
                 2.scala中有嵌套函数和匿名函数
                   3.scala支持高阶函数
                 4.scala支持偏应用(偏函数)
                 5.scala支持闭包

      举例来说:

      1.可传递
      

     1 def  func(f:()  =>  String)  =  println(f())
     2 func(()  =>  "hi")
     3 //output:  hi
     4         
     5 def  foo()  =  "ok"
     6 func(foo)
     7 //output:  ok
     8         
     9 val  fun  =  (x:Int)  =>  print(x)
    10 fun(2)
    11 //output:2

      2.嵌套函数

    1 def foo(){
    2     def bar(){
    3         println("hi")
    4         }
    5     bar  //exec
    6 }
    7 
    8 foo //output:hi        


    嵌套函数在实际中应用场景不多,其中一个场景是将递归函数转为尾递归方式!

     1 def fun1(){
     2   .....
     3   this      
     4 }
     5 
     6 def fun2(){
     7   ....
     8   this
     9 }
    10 
    11 //两个函数可以如下方式使用
    12 fun1().fun2()

      3.匿名函数

    1 lambda:函数字面量(Function literal)
    2 (x:Int,y:Int) => x +y
    3 参数 右箭头 函数体
    4 
    5 上面语句产生一段匿名函数,类型为(Int,Int) => Int
    6 注意:scala中函数的参数个数为0到22个

      4.高阶函数

     1 第一种:用函数做参数的函数。eg:
     2 
     3 def f2(f:() => Unit) {f()}
     4 
     5 def f1(){println(1)}
     6 
     7 f2(f1)
     8 
     9 f2(() => println("hi")) //传入匿名函数
    10 
    11 第二种:产生的结果是一个函数的函数。eg:
    12 
    13 def hf():Int => Int = x => x +1
    14 
    15 val fun = hf
    16 
    17 fun(2) //output:3


      5.函数柯里化

     1 当函数具有多个参数时
     2 def sum(x:Int,y:Int) = x + y
     3 
     4 //参数被打散后,两个参数分开
     5 def sum2(x:Int)(y:Int) = x + y
     6 
     7 sum2(1)(2) //output:3
     8 
     9 scala> def first(x:Int)=(y:Int) => x+y
    10 first: (x: Int)Int => Int
    11 
    12 scala> first(1)
    13 res10: Int => Int = <function1>
    14 
    15 scala> val second=first(1)
    16 second: Int => Int = <function1>
    17 
    18 scala> second(2)
    19 res11: Int = 3
    20 
    21 函数链
    22 把一个带有多个参数的函数,转换为多个只有一个参数的函数来执行
    23 
    24 f(1)(2)(3) 相当于 ((f(1))(2))(3)
    25 
    26 带入参数 1执行 fa(1) 然后 带入参数2执行 fb(2) 接着带入参数3执行fc(3) 最后得到结果
    27 
    28 柯里化的实际用途?
    29 控制抽象,可改变代码的书写风格 foo(res,()=>println(res)) foo(res)(()=> println(res)) foo(res){()=> println(res)}
    30 实现部分应用函数
    31 scala> def log(time:java.util.Date,msg:String){println(time+msg)}
    32 log: (time: java.util.Date, msg: String)Unit
    33 
    34 scala> val log2 = log(new java.util.Date,_:String)
    35 log2: String => Unit = <function1>
    36 
    37 scala> log2("test1")
    38 Mon Sep 09 23:46:15 CST 2013test1
    39 
    40 scala> log2("test2")
    41 Mon Sep 09 23:46:19 CST 2013test2
    42 
    43 scala> log2("test3")
    44 Mon Sep 09 23:46:22 CST 2013test3


      6.闭包

     1 在java中匿名内部类访问局部变量是,局部变量必须声明为final(类似闭包的实现)
     2 
     3 scala中没有那么麻烦:
     4 
     5 scala> val more = 1
     6 more: Int = 1
     7 
     8 scala> val addMore = (x: Int) => x + more
     9 addMore: Int => Int = <function1>
    10 
    11 scala> addMore(10)
    12 res19: Int = 11

    (以上案例部分参考互联网已公开的案例和<Programming in Scala>中部分说明)

    2、scala简单的并发编程模型

      scala的并发编程采用的是actor模型,即参与者模型(国内有个通俗术语叫做观察者模式)。

      简而言之就是每个参与者将自身的状态变化通过某种方式广播出去,其他参与者获取到这种状态变化后,再决定是否继续参与。

      scala使用精炼的函数式编程实现了actor模型,从而可以实现同一JVM单核并发,同一JVM多核并发,多个JVM之间并发,并且还可以实现某种意义上的IPC。

      典型的actor编程模型如下:

      

     1 Scala写法1:
     2 
     3 import actors.Actor,actors.Actor._
     4 
     5 class A1 extends Actor {
     6 
     7 def act { 
     8     react { 
     9         case n:Int=>println(perfect(n)) 
    10         }
    11     }
    12 }
    13 
    14 n to n+10 foreach (i=>{ 
    15     (new A1).start ! i
    16     }
    17 )
    1 val aa = Array.fill(11)(actor { 
    2     react { 
    3         case n:Int=>println(perfect(n)) 
    4         }
    5     }
    6 )
    7 
    8 n to n+10 foreach (i=>aa(i-n) ! i)

      两种写法只是区别在声明类方式上面,一种需要显式调用start,另外一个不需要而已。

      不同JVM之间的通讯模型如下:

      服务端:

      

     1 import scala.actors._
     2 import scala.actors.Actor._
     3 import scala.actors.remote._
     4 import scala.actors.remote.RemoteActor._
     5 import org.andy.scala.actor.model.ActorDeal
     6 
     7 class ActorServer extends Actor {
     8   
     9     def act(){
    10       
    11       alive(9999) //绑定端口
    12       register('ActorServer, self) //注册服务类
    13       
    14       
    15       while(true){
    16         receive  {
    17           case str:String =>print("There is say "+str)
    18           case _=>println("There is no message ")
    19         }
    20       }
    21       
    22     }
    23 }

      客户端:

     1 import scala.actors._
     2 import scala.actors.Actor._
     3 import scala.actors.remote._
     4 import scala.actors.remote.RemoteActor._
     5 import scala.actors.Actor
     6 import org.andy.scala.actor.model.ActorDeal
     7 
     8 class ActorClient extends Actor {
     9     def act(){
    10       val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)
    11           //每隔5秒发送一次   
    12       while(true){
    13         actServer ! "Hello "
    14         print("===Send Hello==  ")
    15         Thread.sleep(5000)
    16       }
    17     }
    18 }

      其中后的效果如下:

    客户端
    client init success
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    ===Send Hello==  ===Send ad==
    服务端
    server init success
    There is say Hello
    There is say Hello
    There is say Hello
    There is say Hello
    There is say Hello

      这个模型是最简单的不同JVM之间的通讯,我们再添加一点难度!传递一个对象尝试一下:

      对象定义如下:

    1 class ActorDeal extends Serializable {
    2 
    3   var msg: String = ""
    4 
    5   def dealPrint() = {
    6     println("From deal " + msg)
    7   }
    8 }

      客户端:

     1 import scala.actors._
     2 import scala.actors.Actor._
     3 import scala.actors.remote._
     4 import scala.actors.remote.RemoteActor._
     5 import scala.actors.Actor
     6 import org.andy.scala.actor.model.ActorDeal
     7 
     8 class ActorClient extends Actor {
     9     def act(){
    10       val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)
    11       var ad = new ActorDeal()
    12       ad.msg ="WORLD"
    13       while(true){
    14         actServer ! "Hello "
    15         print("===Send Hello==  ")
    16         actServer!ad
    17         println("===Send ad==")
    18         Thread.sleep(5000)
    19       }
    20     }
    21 }

      高亮部分为新增的对象操作

      服务端:

     1 import scala.actors._
     2 import scala.actors.Actor._
     3 import scala.actors.remote._
     4 import scala.actors.remote.RemoteActor._
     5 import org.andy.scala.actor.model.ActorDeal
     6 
     7 class ActorServer extends Actor {
     8     RemoteActor.classLoader= getClass().getClassLoader()
     9   
    10     def act(){
    11       
    12       alive(9999)
    13       register('ActorServer, self)
    14       
    15       
    16       while(true){
    17         receive  {
    18           case ad:ActorDeal => dealAD(ad)
    19           case str:String =>print("There is say "+str)
    20           case _=>println("There is no message ")
    21         }
    22       }
    23       
    24     }
    25     
    26     def dealAD(adm:ActorDeal)={
    27       println("Receive AD")
    28       adm.dealPrint
    29       
    30     }
    31 }

      标红的语句是最重要的一句,如果没有这句,scala actor将会报ClassNotFound异常。所以一定要添加上去

      好,运行后的结果如下:

    1 server init success
    2 There is say Hello Receive AD
    3 From deal WORLD
    4 There is say Hello Receive AD
    5 From deal WORLD
    6 There is say Hello Receive AD
    7 From deal WORLD

      既然写到分布式编程了,那么就再添加一点reply的东西。

      下面的代码表示的服务端如何给客户端回复响应,请看代码:

      服务端

      

    import scala.actors._
    import scala.actors.Actor._
    import scala.actors.remote._
    import scala.actors.remote.RemoteActor._
    import org.andy.scala.actor.model.ActorDeal
    
    class ActorServer extends Actor {
        RemoteActor.classLoader= getClass().getClassLoader()
      
        def act(){
          
          alive(9999)
          register('ActorServer, self)
          
          
          while(true){
            receive  {
              case ad:ActorDeal => dealAD(ad)
              case str:String =>print("There is say "+str)
              case _=>println("There is no message ")
            }
          }
          
        }
        
        def dealAD(adm:ActorDeal)={
          println("Receive AD")
          adm.dealPrint
          reply("Yet I receive")
        }
    }

      高亮部分就服务端的回复语句。既然服务端有回复,那么客户端是不是也要关心一下呢?

      客户端

      

    import scala.actors._
    import scala.actors.Actor._
    import scala.actors.remote._
    import scala.actors.remote.RemoteActor._
    import scala.actors.Actor
    import org.andy.scala.actor.model.ActorDeal
    
    class ActorClient extends Actor {
        def act(){
          val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)
          var ad = new ActorDeal()
          ad.msg ="WORLD"
          while(true){
            actServer ! "Hello "
            print("===Send Hello==  ")
            var fu =actServer!!ad
            println("===Send ad==")
            var result = fu() 
            println("===Receive=="+result)
            Thread.sleep(5000)
          }
        }
    }

      首先客户端调用“!!”就是一个等待响应的阻塞方法,这里只要收到服务端回复的确认字符串即可。

      结果如下:

      

    client init success
    ===Send Hello==  ===Send ad==
    ===Receive==Yet I receive

       如果我们增加点难度,回复一个对象。那又该如何处理呢?请看代码:

      服务端:

    import scala.actors._
    import scala.actors.Actor._
    import scala.actors.remote._
    import scala.actors.remote.RemoteActor._
    import org.andy.scala.actor.model.ActorDeal
    
    class ActorServer extends Actor {
        RemoteActor.classLoader= getClass().getClassLoader()
      
        def act(){
          
          alive(9999)
          register('ActorServer, self)
          
          
          while(true){
            receive  {
              case ad:ActorDeal => dealAD(ad)
              case str:String =>print("There is say "+str)
              case _=>println("There is no message ")
            }
          }
          
        }
        
        def dealAD(adm:ActorDeal)={
          println("Receive AD")
          adm.dealPrint
          adm.msg ="I have achieve target"
          reply(adm)
        }
    }

      我们修改了对象数据,然后reply回去。

      这次客户端会有大动作,请看:

    import scala.actors._
    import scala.actors.Actor._
    import scala.actors.remote._
    import scala.actors.remote.RemoteActor._
    import scala.actors.Actor
    import org.andy.scala.actor.model.ActorDeal
    
    class ActorClient extends Actor {
        RemoteActor.classLoader = getClass().getClassLoader()
        def act(){
          val actServer = select(Node("127.0.0.1", 9999), 'ActorServer)
          var ad = new ActorDeal()
          ad.msg ="WORLD"
          while(true){
            actServer ! "Hello "
            print("===Send Hello==  ")
            var fu =actServer!!ad
            println("===Send ad==")
            var result = fu()
            **********************
            Thread.sleep(5000)
          }
        }
    }

      首先一定要重置classloader,否则又会报ClassNotFound。后面result就应该是接受回复的ActorDeal对象了,但fu()返回的是any对象,又如何转换为ActorDeal对象呢?

      请点击这里查看Scala如何类型强转 ,具体代码里面写的较为详细了。

      我们看看效果:

      

    client init success
    ===Send Hello==  ===Send ad==
    From deal I have achieve target

      scala其他的特点,比如:强类型,扩展性这里就不一一描述了。

      

      上述的两点,应该属于scala与java之间最根本的特征了。

      

  • 相关阅读:
    k8s运行容器之Job应用(6)
    k8s创建资源的两种方式及DaemonSet应用(5)
    kubernetes架构及deployment应用(4)
    docker部署harbor私有镜像库(3)
    k8s集群部署(2)
    kubernetes介绍(1)
    Docker网络(5)
    Docker存储(4)
    Docker镜像的仓库及底层依赖的核心技术(3)
    Docker的镜像及容器常用操作(2)
  • 原文地址:https://www.cnblogs.com/vikings-blog/p/3942417.html
Copyright © 2011-2022 走看看