Scala笔记一
来源:互联网 发布:淘宝网羽绒服布料 编辑:程序博客网 时间:2024/06/05 19:12
- 保留字
- 分号
- 变量声明
- Range
- 偏函数
- 示例
- 代码
- 运行
- 运行结果
- 示例
- 方法声明
- 方法默认值和命名参数列表
- 示例
- 代码
- 示例
- 方法具有多个参数列表
- 示例
- 代码
- 调用有多个参数列表的draw方法
- 优势
- 示例
- Future简介
- 示例
- 代码
- 运行
- 运行结果
- 说明
- 示例
- 嵌套方法的定义和递归
- 代码示例
- 代码
- 运行
- 输出
- 代码示例
- 方法默认值和命名参数列表
- 字面量
- 整数字面量
- 整数字面量
- 浮点数字面量
- 示例
- 布尔型字面量
- 字符字面量
- 字符常量示例
- 字符转义序列
- 字符串字面量
- 符号字面量
- 函数字面量
- 元组字面量
- 定义
- 使用
- 运行
- 输出
- 两元素的元组
- 整数字面量
- Option SomeNone 避免使用null
- 封闭类的继承
- 用文件和名空间组织代码
- 导入类型及其成员
- 示例
保留字
:在参数化类型和抽象类型生命中,用于限制允许的类型 # 在类型注入中使用 @ 注解
Scala不存在break
和continue
关键字
分号
- 分号是表达式之间的间隔
- 当一行结束时,Scala就认为表达式结束了,除非它可以判断出该表达式尚未结束
变量声明
- Scala允许声明变量是可变的还是不可变的
- 声明不可变变量使用val
- 声明可变变量使用var
// 声明不可变变量,这里只是array不可再更改,但是数组内容可以更改val array:Array[String] = new Array(5)// 可变var price: Double = 1.1
Range
- 生成从某个起点到某个终点的一个数字序列
- 支持
Int
,Long
,Float
,Double
,Char
,BigInt
,BigDecimal
- 使用
to
包括区间上限 - 使用
until
不包括区间上限 - 使用
by
设置步长
scala> 1 to 5res2: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5)scala> 1 until 5res3: scala.collection.immutable.Range = Range(1, 2, 3, 4)scala> 1 to 10 by 3res0: scala.collection.immutable.Range = Range(1, 4, 7, 10)scala> 0.1f to 5.3f by 1.0fres1: scala.collection.immutable.NumericRange[Float] = NumericRange(0.1, 1.1, 2.1, 3.1, 4.1, 5.1)scala> 'a' to 'g'res2: scala.collection.immutable.NumericRange.Inclusive[Char] = NumericRange(a, b, c, d, e, f, g)scala> BigInt(1) to BigInt(5) by 2res3: scala.collection.immutable.NumericRange[BigInt] = NumericRange(1, 3, 5)
偏函数
- 不处理所有可能的输入,只处理那些能与至少一个
case
语句匹配的输入 - 在偏函数中,只能使用
case
语句 - 整个函数必须用花括号包围
- 如果偏函数被调用,而函数的输入却与所有语句都不匹配,系统就会抛出一个
MatchError
运行时错误 - 使用
isDefineAt
方法测试特定输入是否与偏函数匹配 - 偏函数链式连接: pf1 orElse pf2 orElse pf3 … 只有所有偏函数都不匹配,才会抛出
MatchError
示例
代码
// file: pf.scalavar pf1: PartialFunction[Any, String] = { case s: String => "YES"}var pf2: PartialFunction[Any, String] = { case d: Double => "YES"}val pf = pf1 orElse pf2def tryPF(x: Any, f: PartialFunction[Any, String]): String = try {f(x).toString} catch {case _: MatchError => "ERROR!"}def d(x: Any, f: PartialFunction[Any,String]) = f.isDefinedAt(x).toStringprintln(" | pf1 - String | pf2 - Double | pf - All")println("x | def? | pf1(x) | def? | pf2(x) | def? | pf(x)")println("+" * 50)List("str", 3.14, 10) foreach { x => printf("%-5s | %-5s | %-6s | %-6s | %-6s | %-5s | %-6s\n", x.toString, d(x, pf1), tryPF(x, pf1), d(x, pf2), tryPF(x, pf2), d(x, pf), tryPF(x, pf))}
运行
scala pf.scala
运行结果
| pf1 - String | pf2 - Double | pf - Allx | def? | pf1(x) | def? | pf2(x) | def? | pf(x)++++++++++++++++++++++++++++++++++++++++++++++++++str | true | YES | false | ERROR! | true | YES 3.14 | false | ERROR! | true | YES | true | YES 10 | false | ERROR! | false | ERROR! | false | ERROR!
方法声明
方法默认值和命名参数列表
- 可以为方法参数提供默认值
- 调用方法时可以只提供部分参数值,可以只传入指定参数
示例
代码
case class Point(x: Double = 0.0, y: Double = 0.0) { def shift(deltax: Double = 0.0, deltay: Double = 0.0) = copy (x + deltax, y + deltay)}val p1 = new Point(x = 3.3, y = 4.4)val p2 = p1.copy(y = 6.6)
方法具有多个参数列表
示例
代码
abstract class Shape() { def draw(offset: Point = Point(0.0, 0.0))(f: String => Unit): Unit = f(s"draw(offset = $offset), ${this.toString}")}case class Circle(center: Point, radius: Double) extends Shape
调用有多个参数列表的draw
方法
s.draw(Point(1.0, 2.0))(str => println(s"ShapesDrawingActor: $str"))// 也可以将圆括号替换为花括号s.draw(Point(1.0, 2.0)){str => println(s"ShapesDrawingActor: $str")}// 或者这样s.draw(Point(1.0, 2.0)){str => println(s"ShapesDrawingActor: $str")}// 亦或这样s.draw(Point(1.0, 2.0)){ str => println(s"ShapesDrawingActor: $str")}
优势
- 代码更清晰
- 在之后的参数列表中进行类型判断
- 可以用最后一个参数列表来推断隐含参数.隐含参数是用
implicit
关键字声明的参数.
Future简介
scala.concurrent.Future
是Scala提供的一个并发工具,其中的API使用隐含参数来减少冗余代码- 将任务封装在Future中执行时,该任务的执行是异步的
示例
代码
并发发出5个任务,并在任务结束时处理任务返回的结果.
// file: future.scalaimport scala.concurrent.Futureimport scala.concurrent.ExecutionContext.Implicits.globaldef sleep(millis: Long) = { Thread.sleep(millis)}def doWork(index: Int) = { sleep((math.random * 1000).toLong) index}(1 to 5) foreach { index => val future = Future(doWork(index)) future onSuccess { case answer: Int => println(s"Success! returned: $answer") } future onFailure { case th: Throwable => println(s"Failure! returned: $th") }}sleep(3000) // 等待足够长时间,确保工作进程结束println("finito!")
运行
scala future.scala
运行结果
Success! returned: 2Success! returned: 4Success! returned: 1Success! returned: 5Success! returned: 3finito!
说明
用foreach
对一个从1到5的Range
进行迭代,调用了scala.concurrent.Futrue.apply
, 这是单例对象Future的工厂方法.Future.apply
返回一个新的Future
对象,然后控制权就交给循环了,该对象将在另一个线程中执行doWork(index)
- 用onSuccess注册一个回调函数,当future成功执行完毕后,该回调函数会被执行.这个回调函数是一个偏函数.
- Future API允许我们通过ExecutionContext来配置并发操作的执行.
import scala.concurrent.ExecutionContext.Implicits.global
语句导入了默认的ExecutionContext.示例中调用了3个方法,其中的这些方法的第二个参数列表具有隐含的ExecutionContext参数,由于没有指定,使用了默认的ExecutionContext. - 使用
implicit
关键字声明变量为implicit.只有被声明为implicit的函数参数才允许调用时不给出实参.
嵌套方法的定义和递归
方法的定义可以嵌套.
代码示例
代码
// file: factorial.scaladef factorial(i: Int): Long = { def fact(i: Int, accumulator: Int): Long = { if (i <= 1) accumulator else fact(i - 1, i * accumulator) } fact(i, 1)}(0 to 5) foreach ( i => println(factorial(i)) )
运行
scala factorial.scala
输出
112624120
字面量
整数字面量
- 整数字面量可以以十进制,八进制,十六进制的形式出现
整数字面量
- 如果整数字面量的值超出了以上表格中所示的范围,将会引发一个编译错误.
- 字面量类型默认推断为Int
浮点数字面量
- 默认推断类型为Double
示例
.143.143.14F3.14D3E53.14e-53.14e+53.14e-4D
布尔型字面量
布尔型字面量可以为true
或false
字符字面量
- 字符字面量要么是单引号内的一个可打印的Unicode字符,要么是一个转义序列.
- 值在0~255的Unicode字符可以用八进制数字的转义形式表示,即一个反斜杠后面跟上最多三个八进制数字字符
字符常量示例
'A''\u0041''\n''012''\t'
字符转义序列
不可打印的Unicode字符是不允许的,如\u0009
(水平制表符), 应该使用等价的转义形式\t
字符串字面量
- 字符串字面量是被双引号和三重双引号包围的字符串序列
符号字面量
- 符号是一些规定的字符串
- 符号字面量是单引号后更上一个或多个数字,字母或下划线,但第一个字符不能是数字
- 符号字面量
'id
是表达式scala.Symbol("id")
的简写形式 - 如果需要创建包含空格的符号,可以使用
Symbol.apply
, 如Symbol.apply(" Programming Scala ")
函数字面量
(i: Int, s: String) => s+i
是一个类型为Function2[Int, String, String]
(返回值类型为String)的函数字面量我们可以使用函数字面量来声明变量,下面两种声明是等价的:
val f1: (Int, String) => String = (i, s) => s+ival f2: Function2[Int, String, String] = (i, s) => s+i
元组字面量
- Scala库中包含TupleN类,如Tuple2, 用于组建N元素组
定义
val tup = ("strig", 2016) // 定义了一个Tuple2的实例val t1: (Int, String) = (1, "one")val t2: Tuple2[Int, String] = (2, "two")
使用
// File: tuple.scalaval t = ("Hello", 1, 2.3)println("print the whole tuple:" + t)println("print the first item:" + t._1)println("print the second item:" + t._2)println("print the third item:" + t._3)val (t1, t2, t3) = ("World", '!', 0x22)println(t1 + ", " + t2 + ", " + t3)val (t4, t5, t6) = Tuple3("World", '!', 0x22)println(t4 + ", " + t5 + ", " + t6)
运行
scala tuple.scala
输出
print the whole tuple:(Hello,1,2.3)print the first item:Helloprint the second item:1print the third item:2.3World, !, 34World, !, 34
两元素的元组
两元素的元组有时被简称为pair.其定义方法有多种:
(1, "one")
1 -> "one"
Tuple2(1, "one")
示例:
scala> val t = 1 -> "one"t: (Int, String) = (1,one)scala> t._1res0: Int = 1scala> t._2res1: String = one
Option, Some,None: 避免使用null
Option
有两个具体的子类,Some
和None
.Some
表示有值None
表示没有值
封闭类的继承
- Scala设计了关键字
sealed
,其告诉编译器所有的子类必须在同一个源文件中声明.在Scala库中,Some与None就是与Option声明在同一源文件中,这一技术有效防止了Option类派生其他子类型. - 如果要防止用户派生任何子类, 可以用
final
关键字声明
用文件和名空间组织代码
- Scala沿用Java用包来表示命名空间的这一做法,但它更加灵活.
- 文件名不必与类名一致
- 包结构不一定要与目录结构一致
- 可以定义与文件的”物理”位置独立的包结构
- Scala不允许在脚本中定义包,脚本被隐含包装在一个对象中.在对象中声明包是不允许的
- 不能再类或对象中定义包
导入类型及其成员
_
被当做通配符, 因为在Scala中,*
允许用作函数名
示例
Scala中导入Java类型.
import java.awt._ // 导入包内所有类型import java.io.File // 导入包中单独的Scala类型或Java类型import java.io.File._ // 导入了java.io.File中所有的静态方法和属性.与之等价的Java import语句为: // import static java.io.File.*import java.util.{Map, HashMap} // 选择性导入
- 导入是相对的
0 0
- Scala学习笔记一
- Scala学习笔记(一)
- scala学习笔记一
- Scala学习笔记一
- scala笔记(一)
- scala学习笔记一
- Scala笔记一
- scala笔记(一)
- scala学习笔记一
- scala学习笔记☞一---------Scala 初探
- Scala学习笔记(一)----Scala环境安装
- 《Scala入坑笔记》一、Scala简介
- scala学习笔记一------初步了解scala
- [Scala]Scala学习笔记一 基础
- Scala学习笔记(一)
- scala学习笔记(一)
- SCALA学习笔记(一)
- Scala学习笔记(一)
- 【socket】深入浅出讲解:php的socket通信
- hoj1030-Labyrinth
- 移除所有子视图,无需循环只需要一句代码
- maven引入私服jar
- 认识双阶乘
- Scala笔记一
- 瀑布流 collectionView实现
- 单点登录SSO,统一认证oAuth名词解释
- 关于EasyUI Datagrid JSON对象内嵌对象的取值问题
- Android APK加壳技术方案【2】
- Hive窗口函数
- TCP和UDP的区别(转)
- cocos2dx的runAction: 重复执行,多个动作连接执行,多个动作同时执行的实现
- GO实现简单的web服务功能