Java与scala的选择问题

10 篇文章 0 订阅

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(</span>9999<span style="color: #000000;">)
  register(</span>'ActorServer, self)
  
  
  <span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">){
    receive  {
      </span><span style="color: #0000ff;">case</span> ad:ActorDeal =&gt;<span style="color: #000000;"> dealAD(ad)
      </span><span style="color: #0000ff;">case</span> str:String =&gt;print("There is say "+<span style="color: #000000;">str)
      </span><span style="color: #0000ff;">case</span> _=&gt;println("There is no message "<span style="color: #000000;">)
    }
  }
  
}

def dealAD(adm:ActorDeal)</span>=<span style="color: #000000;">{
  println(</span>"Receive AD"<span style="color: #000000;">)
  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(</span>9999<span style="color: #000000;">)
  register(</span>'ActorServer, self)
  
  
  <span style="color: #0000ff;">while</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">){
    receive  {
      </span><span style="color: #0000ff;">case</span> ad:ActorDeal =&gt;<span style="color: #000000;"> dealAD(ad)
      </span><span style="color: #0000ff;">case</span> str:String =&gt;print("There is say "+<span style="color: #000000;">str)
      </span><span style="color: #0000ff;">case</span> _=&gt;println("There is no message "<span style="color: #000000;">)
    }
  }
  
}

def dealAD(adm:ActorDeal)</span>=<span style="color: #000000;">{
  println(</span>"Receive AD"<span style="color: #000000;">)
  adm.dealPrint
  <span style="background-color: #00ff00;">adm.msg </span></span><span style="background-color: #00ff00;">="I have achieve target"</span><span style="color: #000000;"><span style="background-color: #00ff00;">
  reply(adm)</span>
}

}

复制代码

  我们修改了对象数据,然后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之间最根本的特征了。

  

如果您认为此文章对您有所帮助,请您点击推荐。进步来源于思想的碰撞,所以欢迎大家踊跃留言评论。
分类: spark
标签: scala, java
1
0
« 上一篇: scala actor编程之对象传递
» 下一篇: Ubuntu 常用命令
	</div>
	<p class="postfoot">
		posted on <span id="post-date">2014-08-28 21:17</span> <a href="https://www.cnblogs.com/vikings-blog/">vikings`s blog</a> 阅读(<span id="post_view_count">9660</span>) 评论(<span id="post_comment_count">0</span>)  <a href="https://i.cnblogs.com/EditPosts.aspx?postid=3942417" rel="nofollow">编辑</a> <a href="#" onclick="AddToWz(3942417);return false;">收藏</a>
	</p>
</div>
<script type="text/javascript">var allowComments=true,cb_blogId=190010,cb_entryId=3942417,cb_blogApp=currentBlogApp,cb_blogUserGuid='62e17e75-18ee-e311-8d02-90b11c0b17d6',cb_entryCreatedDate='2014/8/28 21:17:00';loadViewCount(cb_entryId);var cb_postType=1;</script>

</div><a name="!comments"></a><div id="blog-comments-placeholder"></div><script type="text/javascript">var commentManager = new blogCommentManager();commentManager.renderComments(0);</script>

导航

<2018年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

公告

昵称: vikings`s blog
园龄: 4年6个月
粉丝: 51
关注: 13
+加关注

最新评论

  • 1. Re:破解钉钉打卡
  • 2018.11.21最新钉钉破解方法要很隐蔽安全的, 为了工作安全,一定要稳妥:
  • --歌手叶子
  • 2. Re:破解钉钉打卡
  • 可以任意位置打卡,我这有方法-V信sslee0067
  • --linuxos
  • 3. Re:我们是80后 golang入坑系列
  • := 这种变量声明语法真烂, 瞬间不想学了, 要是2种混用就是一种灾难, 最后就是一种垃圾代码
  • --boveyyun
  • 4. Re:Docker学习总结之docker入门
  • 很赞,让我对docker的认识又近了一步
  • --superc2006
  • 5. Re:破解钉钉打卡
  • 现在钉钉最新版本是3.5.1 楼主的软件已经偏老了,技术跟不上,有安全隐患,我们公司已经研发出适配最新版本钉钉的技术,关键是安全稳定好用!可以提供免费试用 官方 V欣 130 6762 1851
  • --Mg考勤系统支持各类打卡考勤
<a id="Footer1_Hyperlink3" name="Hyperlink1" href="https://www.cnblogs.com/" style="font-family:Verdana;font-size:12px;">博客园</a>
<br>
Copyright © vikings`s blog

id="google_osd_static_frame_7472715736930">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值