一、Values
Values是Scala中的数据类型,相当于在Java的基础上加了Tuple和Option,Array和java的普通数组一样
1.1 Tuples
Tuple是一个长度固定的集合,它里面可以放不同的数据类型,如
val t = (1, true, "hello")
t._1
t._2
Tuple的最大长度是22,大部分的tuple应该是比较小的,因为如果大了的话角标和元素的对应关系容易弄混,如果想用大的tuple,可以考虑用Class或者Case Class替代。
1.2 Arrays
Scala Arrays和Java的[] 一样,都是长度固定的,Array可以用val a = Array[T](a, b, c)或者val a2 = new Array[T](len)来声明,用a(n)来访问,而不是a[n]
@ val a = Array[Int](1, 2, 3, 4)
a: Array[Int] = Array(1, 2, 3, 4)
@ a(2)
res1: Int = 3
@ val a2 = new Array[Int](5)
a2: Array[Int] = Array(0, 0, 0, 0, 0)
@ a2(2) = 1
@ a2
res4: Array[Int] = Array(0, 0, 1, 0, 0)
1.3 Options
Options类型可以使我们可以表达一个可能存在也可能不存在的值,Option[T]仅有两个值:Somg(v: T)代表有值,None代表无值
@ def hello(title: String, firstName: String, lastNameOpt: Option[String]) = {
lastNameOpt match {
case Some(lastName) => println(s"Hello $title. $lastName")
case None => println(s"Hello $firstName")
}
}
defined function hello
@ hello("Mr", "Haoyi", None)
Hello Haoyi
@ hello("Mr", "Haoyi", Some("Li"))
Hello Mr. Li
Options是一个非常简单的集合,它的size是0或1,我们像可以像普通集合一样遍历Options,或者标准集合操作对Options进行转化,如.map
@ def hello2(name: Option[String]) = {
for(s <- name) println(s"Hello $s")
}
defined function hello2
@ hello2(None)
@ hello2(Some("Haoyi"))
Hello Haoyi
@ def nameLength(name: Option[String]) = {
name.map(_.length).getOrElse(-1)
}
defined function nameLength
@ nameLength(Some("Haoyi"))
res13: Int = 5
@ nameLength(None)
res14: Int = -1
二、 Loops, Conditionals, Comprehensions
2.1 yield
for和yield结合使用,可以将循环结果保存在一个新的集合中
@ val a = Array(1, 2, 3, 4)
a: Array[Int] = Array(1, 2, 3, 4)
@ val a2 = for(i <- a) yield i * 2
a2: Array[Int] = Array(2, 4, 6, 8)
@ val a3 = for(i <- a) yield "hello" + i
a3: Array[String] = Array("hello1", "hello2", "hello3", "hello4")
三、 Method and Functions
3.1 Function Values
Function values和method类似,可以传递参数和返回值。但是method不同的是,function本身就是变量,我们可以传递它,或者将其存储到变量中,然后再调用它。
**注意:**与Method不同,function values不能有可选参数,且不能通过[T]这种语法传递类型参数。当一个method被转成function values时,所有的可选参数必须显示指定,类型参数必须是具体的类型。
3.1.1 Methods taking Functions
function values的一个常见用法是将其当作参数传递到method中,这种method被称为“高阶method”
@ class Box(var x: Int) {
def update(f: Int => Int) = x = f(x)
def printMsg(msg: String) = {
println(msg + x)
}
}
defined class Box
@ val b = new Box(1)
b: Box = ammonite.$sess.cmd3$Box@415156bf
@ b.printMsg("Hello")
Hello1
@ b.update(i => i + 5)
@ b.printMsg("Hello")
Hello6
把function当作参数的method,也可以将method当作参数,如:
@ def increment(i: Int): Int = i + 1
defined function increment
@ val b = new Box(123)
b: Box = ammonite.$sess.cmd3$Box@303c55fa
@ b.update(increment)
@ b.x
res12: Int = 124
@ b.update(x => increment(x))
@ b.x
res14: Int = 125
@ b.update(increment(_))
@ b.x
res16: Int = 12
3.1.2 多个参数列表
Method可以被定义成传递多个参数列表,这种高阶函数的写法可以被用于流程控制:
@ def myLoop(start: Int, end: Int)(callback: Int => Unit) = {
for(i <- Range(start, end)) {
callback(i)
}
}
defined function myLoop
@ myLoop(start = 5, end = 10) { i =>
println(s"i has value ${i}")
}
i has value 5
i has value 6
i has value 7
i has value 8
i has value 9
我目前理解如果想在java中实现这种回调函数的功能,可以用多态来实现,如下
interface Process {
void callback(int x);
}
public class TestCallback {
public static void myLoop(int start, int end, Process p) {
for(int i = start; i < end; i++) {
p.callback(i);
}
}
public static void main(String[] args) {
myLoop(5, 10, new Process() { //最普通的写法,接口的匿名实现类
@Override
public void callback(int x) {
System.out.println("i has value " + x);
}
});
}
}
interface Process {
void callback(int x);
}
public class TestCallback {
public static void myLoop(int start, int end, Process p) {
for(int i = start; i < end; i++) {
p.callback(i);
}
}
public static void main(String[] args) {
myLoop(5, 10, x -> System.out.println("i has value " + x)); //lambda表达式,看起来和函数一样
}
}