前言
环境
如果你正在学习或者只想敲几个示例,那么强烈推荐 Scastie,一个嵌在浏览器中的线上编辑器。
如果你更喜欢 REPL 环境在自己的 scala shell 中学习和测试,则需要首先安装 sbt,使用 sbt 进入 scala shell。
安装 sbt
sbt 用来创建,编译,测试且运行 scala 项目。这里介绍如何安装它。
注意:安装 sbt 依赖于 java 环境
由于我的机器是 CentOS,使用 yum 进行安装。
curl https://bintray.com/sbt/rpm/rpm | sudo tee /etc/yum.repos.d/bintray-sbt-rpm.reposudo yum install sbt安装成功后,敲命令 sbt console 进入 REPL 环境
$ sbt console[info] Updated file /root/hello/project/build.properties: set sbt.version to 1.2.8[info] Loading project definition from /root/hello/project[info] Updating ProjectRef(uri("file:/root/hello/project/"), "hello-build")...[info] downloading https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.11.1/log4j-core-2.11.1-tests.jar ...[info] [SUCCESSFUL ] org.apache.logging.log4j#log4j-core;2.11.1!log4j-core.jar(test-jar) (2985ms)[info] Done updating.[info] Set current project to hello (in build file:/root/hello/)[info] Starting scala interpreter...Welcome to Scala 2.12.7 (OpenJDK 64-Bit Server VM, Java 1.8.0_201).Type in expressions for evaluation. Or try :help.
scala>变量
scala 是一种强类型的语言,但是你可以通过 var 进行赋值,它会自动做类型推断(Type Infer)。
通过以下示例,你可以得到一个好消息,则是 scala 不用写分号!但是它必须使用双引号来表示字符串
var s = "hello, world"
println(s)当然你也可以显式地声明变量。好吧,他这个类型声明有点怪,不过如果你写过 typescript,你对它的接受度会好很多。
var s: String = 'hello, world'数据类型 (Type)
scala 分为引用类型与值类型
以下为所有的值类型,Unit 比较特殊些,在 scala 函数必须有返回值,如果实在没有,那返回的就是 Unit,类似于 javascript 中的 undefined 吧。
- Double
- Float
- Long
- Int
- Short
- Byte
- Char
- Boolean
- Unit
操作符 (Operator)
Block
被 {} 包裹称作 Block。Block 中的最后一个表达式的值为 Block 本身的值。另外 Block 与函数一样拥有一个独立的作用域。
var r = { val x = 1 + 1 x + 1}
// 3println(r)类似于 javascript 中的箭头表达式,不过 scala 更加灵活,以下是一个 js 的箭头表达式
const r = (x = 1 + 1, x + 1)
// 3console.log(r)函数 (Function)
在 scala 中,函数是带有参数的表达式
val add = (x: Int, y: Int) => x + y类似于 python 中的 lambda 函数,与 javascript 中的单行箭头函数,他们都是匿名函数并进行赋值,见以下示例
add = lambda x, y: x + yconst add = (x, y) => x + yMethod
与函数类似,使用 def 标记,并在其后注明返回数据类型
def add(x: Int, y: Int): Int = x + y它也可以带有多个参数列表或者不带参数列表
def add(x: Int)(y: Int)(z: Int): Int = x + y + z
// 12println(add(3)(4)(5))
def zero: Int = 0
// 0println(zero)可以使用 Block 来做 Method 的返回值
def add(x: Int, y: Int): Int = { var sum = x + y sum}Class
class Cat(name: String) { def say(): String = "miao~"}
var tom = new Cat("tom")println(tom.say()) // miao~Object
可以理解为 单例模式
// 不需要带参数object IdFactory { private var counter = 0 def create(): Int = { counter += 1 counter }}
IdFactory.create() // 1IdFactory.create() // 2IdFactory.create() // 3依照我的理解,它有点类似于 javascript 中的闭包,如以下 js 代码
const IdFactory = (counter = 0, () => ++counter)
IdFactory() // 1IdFactory() // 2IdFactory() // 3但更像是 javascript 中的 object,如以下 js 代码
const IdFactory = { counter: 0, create () { return ++this.counter }}
IdFactory.create() // 1IdFactory.create() // 2IdFactory.create() // 3Case Class
常用来表示不可修改数据
case class Point(x: Int, y: Int)
var p1 = Point(3, 4)var p2 = Point(30, 40)Trait
trait Greeter { def greet(name: String): Unit = println("hello, " + name)}
class DefaultGreeter extends Greeter
var greeter = new DefaultGreeter()greeter.greet("shanyue")引用类型
String
scala> var str = "hello"str: String = hello
scala> str.map(x => x.toUpper)res4: String = HELLO
scala> str.map(x => 'A')res7: String = AAAAA
scala> str.map(x => "A")res10: scala.collection.immutable.IndexedSeq[String] = Vector(A, A, A, A, A)更多参考官方文档 https://docs.scala-lang.org/overviews/collections/strings.html
Array
scala> var a1 = Array(1, 2, 3)a1: Array[Int] = Array(1, 2, 3)
scala> a1.map(x => x*3)res22: Array[Int] = Array(3, 6, 9)
// 获取 Array 特定位置的值scala> arr.apply(3)res26: Int = 4另外,对于 Array 有 map 与 filter 操作符,其中 _ 代表所包含的元素
scala> var a1 = Array(1, 2, 3)a1: Array[Int] = Array(1, 2, 3)
scala> a1 map (_ * 3)a2: Array[Int] = Array(3, 6, 9)List
scala> var list = List(1, 2, 3, 4, 5)list: List[Int] = List(1, 2, 3, 4, 5)
scala> var list2 = List(6, 7, 8, 9)list2: List[Int] = List(6, 7, 8, 9)
// 获取 List 特定位置的值scala> list.apply(3)res4: Int = 4
// 获取 List 特定位置的值scala> list(3)res7: Int = 4
scala> list ++ list2res8: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
// List 是 immutable 的,无法修改其中的值scala> list(3) = 100<console>:26: error: value update is not a member of List[Int] list(3) = 100 ^List 与 Array 有什么区别
Difference between Array and List in scala
- Array 中的值是可变的,List 是不可变的,List 更符合函数式的思维
Seq
scala> var s = Seq(1, 1, 2)s: Seq[Int] = List(1, 1, 2)Map
可以使用 key -> value 或者 (key, value) 两种形式声明 Map。
scala> var m = Map(("x", 3), ("y", 4), ("z", 5))m: scala.collection.immutable.Map[String,Int] = Map(x -> 3, y -> 4, z -> 5)
scala> var m = Map("x" -> 3, "y" -> 4, "z" -> 5)m: scala.collection.immutable.Map[String,Int] = Map(x -> 3, y -> 4, z -> 5)
// 可以通过 get 方法获取 keyscala> m.get("x")res7: Option[Int] = Some(3)
// get 也可以作为操作符scala> m get "x"res9: Option[Int] = Some(3)
// 也可以直接获取 keyscala> m("x")res10: Int = 3
// 当直接获取 key 时,key 不存在则抛出异常scala> m("X")java.util.NoSuchElementException: key not found: X at scala.collection.MapLike$class.default(MapLike.scala:228) at scala.collection.AbstractMap.default(Map.scala:59) at scala.collection.MapLike$class.apply(MapLike.scala:141) at scala.collection.AbstractMap.apply(Map.scala:59) ... 49 elided
// 当不存在 key 时,则取默认值 100scala> m.getOrElse("X", 100)res13: Int = 100
// 查看 key 是否存在scala> m.contains("X")res16: Boolean = false
// 添加 k/v 对scala> m.updated("a", 100)res19: scala.collection.immutable.Map[String,Int] = Map(x -> 3, y -> 4, z -> 5, a -> 100)
// 添加 k/v 对的操作符形式scala> m + ("a" -> 100)res22: scala.collection.immutable.Map[String,Int] = Map(x -> 3, y -> 4, z -> 5, a -> 100)
scala> var m2 = Map("a" -> 100, "b" -> 200)m2: scala.collection.immutable.Map[String,Int] = Map(a -> 100, b -> 200)
// 拼接两个 Mapscala> m2 ++ mres29: scala.collection.immutable.Map[String,Int] = Map(x -> 3, y -> 4, a -> 100, b -> 200, z -> 5)
// 删除某个 keyscala> m - "x"res31: scala.collection.immutable.Map[String,Int] = Map(y -> 4, z -> 5)
// 删除多个 keyscala> m - ("x", "y")res33: scala.collection.immutable.Map[String,Int] = Map(z -> 5)
scala> m.keysres38: Iterable[String] = Set(x, y, z)
scala> m.valuesres42: Iterable[Int] = MapLike(3, 4, 5)
// 对 value 进行 map 转换scala> m mapValues ((x) => x + 10)res45: scala.collection.immutable.Map[String,Int] = Map(x -> 13, y -> 14, z -> 15)更多 Map 操作参考官方文档 https://docs.scala-lang.org/overviews/collections/maps.html
流程控制
if 语句
在 scala 中没有 ?: 运算符,使用 if 代替
var foo = 3var a = if (foo == 3) 10 else 100for 语句