Scala语法篇
Scala基础篇
数据类型
下表中列出的数据类型都是对象,可以直接对它们调用方法。
数据类型 | 描述 |
---|---|
Byte | 8位有符号补码整数。数值区间为 -128 到 127 |
Short | 16位有符号补码整数。数值区间为 -32768 到 32767 |
Int | 32位有符号补码整数。数值区间为 -2147483648 到 2147483647 |
Long | 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 |
Float | 32 位, IEEE 754 标准的单精度浮点数 |
Double | 64 位 IEEE 754 标准的双精度浮点数 |
Char | 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF |
String | 字符序列 |
Boolean | true或false |
Unit | 表示无值,和其他语言中void等同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。 |
Null | null 或空引用 |
Nothing | Nothing类型在Scala的类层级的最底端;它是任何其他类型的子类型。 |
Any | Any是所有其他类的超类 |
AnyRef | AnyRef类是Scala里所有引用类(reference class)的基类 |
表示Long类型,在数字后面添加L或者l作为后缀;浮点数后面有f或者F后缀时,表示Float类型,否则就是Double
变量
用关键词“var”声明变量,关键词"val"声明常量。
var myName : String = "gyt"
val myAge : Int = 21
scala中不一定要指明数据类型,其数据类型通过变量或常量的初始值推断出来的,因此,在没有指明数据类型的情况下,必须要给出初始值。
访问修饰符
用private关键词修饰,只能被当前类以及当前类的内部类访问到,外层类访问不到。
class Outer{
class Inner{
private def f(){
println("f")
}
class InnerMost{
f() // 正确
}
}
(new Inner).f() //错误
}
用protected关键词修饰,只能被当前类的子类访问。
package p {
class Super {
protected def f() {println("f")}
}
class Sub extends Super {
f()
}
class Other {
(new Super).f() //错误
}
}
没有指定任何修饰符,默认为public,在任何地方都可以被访问。
条件和循环
以下是IF...ELSE语句实例。
object Test {
def main(args: Array[String]) {
var x = 30;
if( x == 10 ){
println("X 的值为 10");
}else if( x == 20 ){
println("X 的值为 20");
}else if( x == 30 ){
println("X 的值为 30");
}else{
println("无法判断 X 的值");
}
}
}
以下是一个使用了 i to j 语法(包含 j)的实例,箭头 <- 用于为变量 a 赋值。
object Test {
def main(args: Array[String]) {
var a = 0;
// for 循环
for( a <- 1 to 10){
println( "Value of a: " + a );
}
}
}
在 for 循环 中你可以使用分号;来设置多个区间,它将迭代给定区间所有的可能值。
object Test {
def main(args: Array[String]) {
var a = 0;
var b = 0;
// for 循环
for( a <- 1 to 3; b <- 1 to 3){
println( "Value of a: " + a );
println( "Value of b: " + b );
}
}
}
for 循环集合的语法如下。
object Test {
def main(args: Array[String]) {
var a = 0;
val numList = List(1,2,3,4,5,6);
// for 循环
for( a <- numList ){
println( "Value of a: " + a );
}
}
}
你可以将 for 循环的返回值作为一个变量存储。
object Test {
def main(args: Array[String]) {
var a = 0;
val numList = List(1,2,3,4,5,6,7,8,9,10);
// for 循环
var retVal = for{ a <- numList
if a != 3; if a < 8
}yield a
// 输出返回值
for( a <- retVal){
println( "Value of a: " + a );
}
}
}
函数式编程(重点)
函数式编程:对于相同的输入永远会得到相同的输出,而且没有任何可以观察的副作用,也不依赖外部的环境状态。参考什么是函数式编程?。
Scala中函数是为完成某一功能的程序语句的集合,类中定义的函数称之为方法。下面是方法的一个实例。
object add{
def addInt( a:Int, b:Int ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
}
可变参数:我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。
object Test {
def main(args: Array[String]) {
printStrings("Runoob", "Scala", "Python");
}
def printStrings( args:String* ) = {
var i : Int = 0;
for( arg <- args ){
println("Arg value[" + i + "] = " + arg );
i = i + 1;
}
}
}
默认参数: scala可以为函数参数指定默认参数值,使用了默认参数,你在调用函数的过程中可以不需要传递参数,这时函数就会调用它的默认参数值,如果传递了参数,则传递值会取代默认值。
object Test {
def main(args: Array[String]) {
println( "返回值 : " + addInt() );
}
def addInt( a:Int=5, b:Int=7 ) : Int = {
var sum:Int = 0
sum = a + b
return sum
}
}
匿名函数:箭头左边是参数列表,右边是函数体。
var inc = (x: Int) => {x+1}
var x = inc(7) - 1
//定义一个函数,以函数作为参数输入
def f(func: String => Unit): Unit = {
func("gyt")
}
var fun = (name: String) => {println(name)}
f(fun)
传名调用:传递的不是具体的值,而是代码块。和一般的传值调用相比,每次使用传名调用时,解释器都会计算一次表达式的值。
def f1(): Int = {
println("f1被调用")
12
}
def f2(a: => Int): Unit = {
println(a)
println(a)
}
f2(f1())
至简原则:
(1)函数中的return可以省略,以最后一行代码作为代码块的返回值。
def f1(name: String): String = {
name
}
(2)如果函数体只有一行代码,可以省略花括号。
def f2(name: String): String = name
(3)如果编译器可以推断出来返回值,那么可以省略(:和返回值类型一起省略)。有意思的是,到这一步,scala函数的形式形如数学中的f(x) = y。
def f3(name: String) = name
(4)如果有return,则(3)不适用。
(5)如果返回值是Unit,可以省略等号和返回值,但是此时花括号不能省略。
def f4(name: String) {
println(name)
}
(6)如果函数没有参数,那么调用它的时候可以直接用函数名。不用加“()”。
闭包:如果一个函数,访问到它的外部(局部)变量的值,那么这个函数和它所处的环境,称为闭包。
柯里化:将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。
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
}
}
字符串
在 Scala 中,字符串的类型实际上是 Java String,它本身没有 String 类。
序号 | 方法及描述 |
---|---|
1 | char charAt(int index)返回指定位置的字符 |
2 | int compareTo(Object o)比较字符串与对象 |
3 | int compareTo(String anotherString)按字典顺序比较两个字符串 |
4 | int compareToIgnoreCase(String str)按字典顺序比较两个字符串,不考虑大小写 |
5 | String concat(String str)将指定字符串连接到此字符串的结尾 |
6 | boolean contentEquals(StringBuffer sb)将此字符串与指定的 StringBuffer 比较。 |
7 | static String copyValueOf(char[] data)返回指定数组中表示该字符序列的 String |
8 | static String copyValueOf(char[] data, int offset, int count)返回指定数组中表示该字符序列的 String |
9 | boolean endsWith(String suffix)测试此字符串是否以指定的后缀结束 |
10 | boolean equals(Object anObject)将此字符串与指定的对象比较 |
11 | boolean equalsIgnoreCase(String anotherString)将此 String 与另一个 String 比较,不考虑大小写 |
12 | byte getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中 |
13 | byte[] getBytes(String charsetName使用指定的字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中 |
14 | void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)将字符从此字符串复制到目标字符数组 |
15 | int hashCode()返回此字符串的哈希码 |
16 | int indexOf(int ch)返回指定字符在此字符串中第一次出现处的索引 |
17 | int indexOf(int ch, int fromIndex)返回在此字符串中第一次出现指定字符处的索引,从指定的索引开始搜索 |
18 | int indexOf(String str)返回指定子字符串在此字符串中第一次出现处的索引 |
19 | int indexOf(String str, int fromIndex)返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始 |
20 | String intern()返回字符串对象的规范化表示形式 |
21 | int lastIndexOf(int ch)返回指定字符在此字符串中最后一次出现处的索引 |
22 | int lastIndexOf(int ch, int fromIndex)返回指定字符在此字符串中最后一次出现处的索引,从指定的索引处开始进行反向搜索 |
23 | int lastIndexOf(String str)返回指定子字符串在此字符串中最右边出现处的索引 |
24 | int lastIndexOf(String str, int fromIndex)返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索 |
25 | int length()返回此字符串的长度 |
26 | boolean matches(String regex)告知此字符串是否匹配给定的正则表达式 |
27 | boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等 |
28 | boolean regionMatches(int toffset, String other, int ooffset, int len)测试两个字符串区域是否相等 |
29 | String replace(char oldChar, char newChar)返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的 |
30 | String replaceAll(String regex, String replacement使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串 |
31 | String replaceFirst(String regex, String replacement)使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串 |
32 | String[] split(String regex)根据给定正则表达式的匹配拆分此字符串 |
33 | String[] split(String regex, int limit)根据匹配给定的正则表达式来拆分此字符串 |
34 | boolean startsWith(String prefix)测试此字符串是否以指定的前缀开始 |
35 | boolean startsWith(String prefix, int toffset)测试此字符串从指定索引开始的子字符串是否以指定前缀开始。 |
36 | CharSequence subSequence(int beginIndex, int endIndex)返回一个新的字符序列,它是此序列的一个子序列 |
37 | String substring(int beginIndex)返回一个新的字符串,它是此字符串的一个子字符串 |
38 | String substring(int beginIndex, int endIndex)返回一个新字符串,它是此字符串的一个子字符串 |
39 | char[] toCharArray()将此字符串转换为一个新的字符数组 |
40 | String toLowerCase()使用默认语言环境的规则将此 String 中的所有字符都转换为小写 |
41 | String toLowerCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为小写 |
42 | String toString()返回此对象本身(它已经是一个字符串!) |
43 | String toUpperCase()使用默认语言环境的规则将此 String 中的所有字符都转换为大写 |
44 | String toUpperCase(Locale locale)使用给定 Locale 的规则将此 String 中的所有字符都转换为大写 |
45 | String trim()删除指定字符串的首尾空白符 |
46 | static String valueOf(primitive data type x)返回指定类型参数的字符串表示形式 |
数组
Scala 语言中提供的数组是用来存储固定大小的同类型元素。下面是声明数组的三种方式。
var z:Array[String] = new Array[String](3)
var zz = new Array[String](3)
var zzz = Array("Runoob", "Baidu", "Google")
模式匹配
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。
object Test {
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y: Int => "scala.Int"
case _ => "many"
}
}
实例中第一个 case 对应整型数值 1,第二个 case 对应字符串值 two,第三个 case 对应类型模式,用于判断传入的值是否为整型,相比使用isInstanceOf来判断类型,使用模式匹配更好。第四个 case 表示默认的全匹配备选项,即没有找到其他匹配时的匹配项,类似 switch 中的 default。
object Test {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配。
迭代器
Scala Iterator(迭代器)不是一个集合,它是一种用于访问集合的方法。迭代器 it 的两个基本操作是 next 和 hasNext。调用 it.next() 会返回迭代器的下一个元素,并且更新迭代器的状态。调用 it.hasNext() 用于检测集合中是否还有元素。让迭代器 it 逐个返回所有元素最简单的方法是使用 while 循环:
object Test {
def main(args: Array[String]) {
val it = Iterator("Baidu", "Google", "Runoob", "Taobao")
while (it.hasNext){
println(it.next())
}
}
}
下表列出了Scala Iterator常用的方法:
序号 | 方法及描述 |
---|---|
1 | def hasNext: Boolean如果还有可返回的元素,返回true。 |
2 | def next(): A返回迭代器的下一个元素,并且更新迭代器的状态 |
3 | def ++(that: => Iterator[A]): Iterator[A]合并两个迭代器 |
4 | def ++[B >: A](that :=> GenTraversableOnce[B]): Iterator[B]合并两个迭代器 |
5 | def addString(b: StringBuilder): StringBuilder添加一个字符串到 StringBuilder b |
6 | def addString(b: StringBuilder, sep: String): StringBuilder添加一个字符串到 StringBuilder b,并指定分隔符 |
7 | def buffered: BufferedIterator[A]迭代器都转换成 BufferedIterator |
8 | def contains(elem: Any): Boolean检测迭代器中是否包含指定元素 |
9 | def copyToArray(xs: Array[A], start: Int, len: Int): Unit将迭代器中选定的值传给数组 |
10 | def count(p: (A) => Boolean): Int返回迭代器元素中满足条件p的元素总数。 |
11 | def drop(n: Int): Iterator[A]返回丢弃前n个元素新集合 |
12 | def dropWhile(p: (A) => Boolean): Iterator[A]从左向右丢弃元素,直到条件p不成立 |
13 | def duplicate: (Iterator[A], Iterator[A])生成两个能分别返回迭代器所有元素的迭代器。 |
14 | def exists(p: (A) => Boolean): Boolean返回一个布尔值,指明迭代器元素中是否存在满足p的元素。 |
15 | def filter(p: (A) => Boolean): Iterator[A]返回一个新迭代器 ,指向迭代器元素中所有满足条件p的元素。 |
16 | def filterNot(p: (A) => Boolean): Iterator[A]返回一个迭代器,指向迭代器元素中不满足条件p的元素。 |
17 | def find(p: (A) => Boolean): Option[A]返回第一个满足p的元素或None。注意:如果找到满足条件的元素,迭代器会被置于该元素之后;如果没有找到,会被置于终点。 |
18 | def flatMap[B](f: (A) => GenTraversableOnce[B]): Iterator[B]针对迭代器的序列中的每个元素应用函数f,并返回指向结果序列的迭代器。 |
19 | def forall(p: (A) => Boolean): Boolean返回一个布尔值,指明 it 所指元素是否都满足p。 |
20 | def foreach(f: (A) => Unit): Unit在迭代器返回的每个元素上执行指定的程序 f |
21 | def hasDefiniteSize: Boolean如果迭代器的元素个数有限则返回 true(默认等同于 isEmpty) |
22 | def indexOf(elem: B): Int返回迭代器的元素中index等于x的第一个元素。注意:迭代器会越过这个元素。 |
23 | def indexWhere(p: (A) => Boolean): Int返回迭代器的元素中下标满足条件p的元素。注意:迭代器会越过这个元素。 |
24 | def isEmpty: Boolean检查it是否为空, 为空返回 true,否则返回false(与hasNext相反)。 |
25 | def isTraversableAgain: BooleanTests whether this Iterator can be repeatedly traversed. |
26 | def length: Int返回迭代器元素的数量。 |
27 | def map[B](f: (A) => B): Iterator[B]将 it 中的每个元素传入函数 f 后的结果生成新的迭代器。 |
28 | def max: A返回迭代器迭代器元素中最大的元素。 |
29 | def min: A返回迭代器迭代器元素中最小的元素。 |
30 | def mkString: String将迭代器所有元素转换成字符串。 |
31 | def mkString(sep: String): String将迭代器所有元素转换成字符串,并指定分隔符。 |
32 | def nonEmpty: Boolean检查容器中是否包含元素(相当于 hasNext)。 |
33 | def padTo(len: Int, elem: A): Iterator[A]首先返回迭代器所有元素,追加拷贝 elem 直到长度达到 len。 |
34 | def patch(from: Int, patchElems: Iterator[B], replaced: Int): Iterator[B]返回一个新迭代器,其中自第 from 个元素开始的 replaced 个元素被迭代器所指元素替换。 |
35 | def product: A返回迭代器所指数值型元素的积。 |
36 | def sameElements(that: Iterator[_]): Boolean判断迭代器和指定的迭代器参数是否依次返回相同元素 |
37 | def seq: Iterator[A]返回集合的系列视图 |
38 | def size: Int返回迭代器的元素数量 |
39 | def slice(from: Int, until: Int): Iterator[A]返回一个新的迭代器,指向迭代器所指向的序列中从开始于第 from 个元素、结束于第 until 个元素的片段。 |
40 | def sum: A返回迭代器所指数值型元素的和 |
41 | def take(n: Int): Iterator[A]返回前 n 个元素的新迭代器。 |
42 | def toArray: Array[A]将迭代器指向的所有元素归入数组并返回。 |
43 | def toBuffer: Buffer[B]将迭代器指向的所有元素拷贝至缓冲区 Buffer。 |
44 | def toIterable: Iterable[A]Returns an Iterable containing all elements of this traversable or iterator. This will not terminate for infinite iterators. |
45 | def toIterator: Iterator[A]把迭代器的所有元素归入一个Iterator容器并返回。 |
46 | def toList: List[A]把迭代器的所有元素归入列表并返回 |
47 | def toMap[T, U]: Map[T, U]将迭代器的所有键值对归入一个Map并返回。 |
48 | def toSeq: Seq[A]将代器的所有元素归入一个Seq容器并返回。 |
49 | def toString(): String将迭代器转换为字符串 |
50 | def zip[B](that: Iterator[B]): Iterator[(A, B)返回一个新迭代器,指向分别由迭代器和指定的迭代器 that 元素一一对应而成的二元组序列 |