Scala学习笔记

来源:互联网 发布:中国crm软件市场规模 编辑:程序博客网 时间:2024/05/16 19:06

Scala语法

函数式,面向对象,JVM
val常量
var变量
函数是一等公民
函数可以作为参数传递
表达式没有返回值时,默认返回Unit
Unit类型?对应于没有值
借贷模式
按名称传递与按值传递参数
def log(msg: String)vsdef log(msg:=>String)
按名称传递参数可以减少不必要的计算和异常
柯里化(Currying)?
def add(x:Int, y:Int) = x + yvs`def add(x:Int) = (y:Int) => x + y
模式匹配:类似switch-case/if-else;case _匹配任何参数
Case Class
map和reduceLeft
尾递归foldLeft
Option: Scala提供了Option机制来解决代码中不断解决null的问题。

Lazy初始化:Lazy可以延迟初始化字段。加上lazy的字段会在第一次访问的时候初始化,而不是类初始化的时候初始化。

并发
Actor
Akka
Actor原理
比线程轻量
可以创建数百万级的Actor
复用线程
Actor和线程是不同的抽象,他们的对应关系是由Dispatcher决定。
Actor与线程没有对应一对一的对应关系。一个Actor可以使用多个线程,一个线程也会被多个Actor复用。
同步返回
异步返回Future onComplete
并行集合

远程Actor

实践
使用Java
相等性
抽取器可以帮助模式匹配进行解构
记忆模式
隐式转换
implicit可以定义一个转换函数,可以在使用相应类型的时候自动转换。
DSL
DSL是Scala最强大武器,可以使一些描述性代码变得极为简单
Scala可以使用Spec2,ScalaTest来测试, DSL可以使测试更方便。

开源项目

Spark

Scala环境搭建

Windows 环境变量
SCALA_HOME c:\Progra~1\Scala
PATH %PATH%;%SCALA_HOME%\bin

Hello World!

object HelloWorld {  def main(args: Array[String]): Unit = {    println("Hello, world!")  }}

scalac编译源代码,类似javac
scalac HelloWorld.scala

使用-d选项将class文件输出到指定目录

scalac -d classes HelloWorld.scala

执行scala
scala HelloWorld

使用-classpath或简写-cp来指定class目录
scala -cp classes HelloWorld

使用脚本

#!/bin/shexec scala "$0" "$@"!#object HelloWorld extends App {  println("Hello, world!")}HelloWorld.main(args)

git@git.tuan800-inc.com:lbs_recommender/recommender-dao-storm.git

参考
Scala指南
Scala
Coursera:Functional Programming Principles in Scala
Getting started with SBT

传名和传值

Scala的解释器在解析函数参数(function arguments)时有两种方式:
传值调用(call-by-value):先计算参数表达式的值,再应用到函数内部;
传名调用(call-by-name):将未计算的参数表达式直接应用到函数内部
在进入函数内部前,传值调用方式就已经将参数表达式的值计算完毕,而传名调用是在函数内部进行参数表达式的值计算的。

偏应用函数

Scala 偏应用函数是一种表达式,你不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。

import java.util.Dateobject Test {   def main(args: Array[String]) {      val date = new Date      val logWithDateBound = log(date, _ : String)      logWithDateBound("message1" )      Thread.sleep(1000)      logWithDateBound("message2" )      Thread.sleep(1000)      logWithDateBound("message3" )   }   def log(date: Date, message: String)  = {     println(date + "----" + message)   }}

柯里化

柯里化(Currying)指的是将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。

实例

首先我们定义一个函数:

def add(x:Int,y:Int)=x+y

那么我们应用的时候,应该是这样用:add(1,2)
现在我们把这个函数变一下形:

def add(x:Int)(y:Int)  = x + y

那么我们应用的时候,应该是这样用:add(1)(2),最后结果都一样是3,这种方式(过程)就叫柯里化。
实现过程

add(1)(2) 实际上是依次调用两个普通函数(非柯里化函数),第一次调用使用一个参数 x,返回一个函数类型的值,第二次使用参数y调用这个函数类型的值。
实质上最先演变成这样一个方法:
def add(x:Int)=(y:Int)=>x+y
那么这个函数是什么意思呢? 接收一个x为参数,返回一个匿名函数,该匿名函数的定义是:接收一个Int型参数y,函数体为x+y。现在我们来对这个方法进行调用。
val result = add(1)
返回一个result,那result的值应该是一个匿名函数:(y:Int)=>1+y
所以为了得到结果,我们继续调用result。
val sum = result(2)
最后打印出来的结果就是3。
完整实例

下面是一个完整实例:

object Test {   def main(args: Array[String]) {      val str1:String = "Hello, "      val str2:String = "Scala!"      println( "str1 + str2 = " +  strcat(str1)(str2) )   }   def strcat(s1: String)(s2: String) = {      s1 + s2   }}

执行以上代码,输出结果为:

$ scalac Test.scala$ scala Teststr1 + str2 = Hello, Scala!

Scala 闭包

闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
闭包通常来讲可以简单的认为是可以访问一个函数里面局部变量的另外一个函数。

闭包的作用?

Scala 集合

Scala 列表类似于数组,它们所有元素的类型都相同,但是它们也有所不同:列表是不可变的,值一旦被定义了就不能改变,其次列表 具有递归的结构(也就是链接表结构)而数组不是。
List.tabulate() 方法是通过给定的函数来创建列表。
方法的第一个参数为元素的数量,可以是二维的,第二个参数为指定的函数,我们通过指定的函数计算结果并返回值插入到列表中,起始值为 0。
Scala Set(集合)是没有重复的对象集合,所有的元素都是唯一的。
Scala 集合分为可变的和不可变的集合。
默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用 scala.collection.mutable.Set 包。
默认引用 scala.collection.immutable.Set
注意: 虽然可变Set和不可变Set都有添加或删除元素的操作,但是有一个非常大的差别。对不可变Set进行操作,会产生一个新的set,原来的set并没有改变,这与List一样。 而对可变Set进行操作,改变的是该Set本身,与ListBuffer类似。
可以使用 ++ 运算符或 Set.++() 方法来连接两个集合。如果元素有重复的就会移除重复的元素。

Map(映射)是一种可迭代的键值对(key/value)结构。

所有的值都可以通过键来获取。
Map 中的键都是唯一的。
Map 也叫哈希表(Hash tables)。
Map 有两种类型,可变与不可变,区别在于可变对象可以修改它,而不可变对象不可以。
默认情况下 Scala 使用不可变 Map。如果你需要使用可变集合,你需要显式的引入 import scala.collection.mutable.Map 类

Scala Option(选项)类型用来表示一个值是可选的(有值或无值)。
Option[T] 是一个类型为 T 的可选值的容器: 如果值存在, Option[T] 就是一个 Some[T] ,如果不存在, Option[T] 就是对象 None 。
通过模式匹配来输出匹配值

object Test {   def main(args: Array[String]) {      val sites = Map("runoob" -> "www.runoob.com", "google" -> "www.google.com")      println("show(sites.get( \"runoob\")) : " +                                            show(sites.get( "runoob")) )      println("show(sites.get( \"baidu\")) : " +                                            show(sites.get( "baidu")) )   }   def show(x: Option[String]) = x match {      case Some(s) => s      case None => "?"   }}

可以使用 getOrElse() 方法来获取元组中存在的元素或者使用其默认的值。

Scala 类和对象

类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
Scala继承一个基类跟Java很相似,只多了两点限制:
1.重写方法需要override关键字
2. 只有主构造函数才可以往基类的构造函数里写参数。
Scala 的副构造函数必须调用主构造函数或另一个构造函数,在 Scala 里主构造函数如同一道关卡,类的实例需要通过他来初始化。

字符串差值

sbt pack plugin

A sbt plugin for creating distributable Scala packages that include dependent jars and launch scripts.

scala 泛型

  //list合并函数,模仿clojure的mergeWith  def mergeWith[KT, VT](f: (VT, VT) => (VT), l1: List[(KT, VT)], l2: List[(KT, VT)]): List[(KT, VT)] = {    val l = l1 ::: l2    l.groupBy(_._1).map(m => (m._1, m._2.map(_._2).reduce(f))).toList  }
0 0
原创粉丝点击