Scala入门
新建Scala代码文件
Scala代码的命名可以不与类名相同,但最好还是遵循这个习惯。例如WordCount.scala
。
声明变量
Scala的变量分为两种类型,一种是可变变量var
,一种是不可变变量val
。在声明变量时,一定要声明是可变变量还是不可变变量。
两者的区别在于val
在声明时就必须被初始化,而且初始化之后就不能再次赋值;var
声明的时候可以进行初始化,也可以进行默认初始化,初始化以后还可以再次对其赋值。默认初始化时一定要声明变量的类型,每一种变量类型都会对应一个默认值,它们可能是不同的。(变量声明比Python要严格)
val s: String = "Hello World!" // 再次赋值会报错
var n: Double = 3.2
var a: Int = _ // 默认初始化
声明变量是可以写出变量的类型,也可以不写,因为Scala可以自动推测变量类型(默认初始化一定要写)。
val x = 99.22
// 返回x: Double = 99.22
Range
Python中的range
函数是一个非常常用的函数,Scala中也有类似的表达式。
1 to 5 // 返回Range(1, 2, 3, 4, 5),左右都是闭的
1 until 5 // 返回Range(1, 2, 3, 4),左闭右开
1 to 10 by 2 // 2是步长
另外,Scala中的range
还支持字符型和浮点型,这是Python不支持的。
'a' to 'z'
0.8 to 6.9 by 0.6
打印
Scala有三种常用的打印函数。
print("hello world") // 不带换行
println("hello world") // 自带换行
printf("hello world") // 用法和C语言一样
if语句
if (x>0) {
println("This is a positive number")
}
else if (x==0) {
println("This is a zero")
}
else {
println("This is a negative number")
}
语法都是差不多的,区别在于Scala的if语句可以用于给变量赋值。
val a = if (x > 0) 1 else 0
Python中也有类似语句。
a = 1 if x > 0 else 0
while语句
var i = 10
while (i < 10) {
println(i)
i -= 1
}
也有do-while语句。
var i = 10
do{
println(i)
i -= 1
}while (i > 0)
for语句
for (i <- 1 to 5) {
println(i)
}
括号中的赋值比较不一样,其中的1 to 5
可以用前面的介绍的Range
代替。
多重循环可以直接在一个for
里面搞定。
for (i <- 1 to 5; j <- 1 to 3) {
println(i*j)
}
for推导式
有时候,我们需要对上述过滤后的结果进行进一步的处理,这时,就可以采用yield关键字,对过滤后的结果构建一个集合。
for (i <- 1 to 5 if i%2==0) yield i // 返回Vector(2, 4)
Array
Array
在Scala中是定长数组,需要注意的是,Scala中使用索引时用的是圆括号,跟其他语言不同。
val intValueArr = new Array[Int](3) //声明一个长度为3的整型数组,每个数组元素初始化为0
intValueArr(0) = 12 //给第1个数组元素赋值为12
intValueArr(1) = 45 //给第2个数组元素赋值为45
intValueArr(2) = 33 //给第3个数组元素赋值为33
Scala还提供了更加简洁的初始化方式。
val intValArr = Array(12,45,33)
val myStrArr = Array("BigData","Hadoop","Spark")
List
List
给我的感觉比较像链表,可以查询表头表尾,还可以用::
操作在头部增加新元素。
val L1 = List(1,2,3)
L1.head // 返回 Int = 1
L1.tail // 返回 List[Int] = List(2, 3)
val L2 = 0::L1 // 返回 L2: List[Int] = List(0, 1, 2, 3)
还可以用:::
操作连接两个列表。
val L3 = L1:::L2 // 返回 L3: List[Int] = List(1, 2, 3, 0, 1, 2, 3)
Tuple
元组可以包含不同类型的元素,直接用圆括号将元素括起来就可以声明一个元组,访问元组中的某个值时也跟之前的不一样,用圆括号会报错。Python中也有元组,跟这个元组的区别是Python的元组就是不可变的。
val tuple = ("scala", 7.21, 'a', 10)
tuple._1 // 返回String = scala
Set
集合是不重复元素的合集,集合中的元素没有顺序,但是允许你快速找到某个元素。Scala 集合分为可变的和不可变的集合。默认情况下,Scala 使用的是不可变集合,如果你想使用可变集合,需要引用scala.collection.mutable.Set
包。
scala> var mySet = Set("Hadoop","Spark")
mySet: scala.collection.immutable.Set[String] = Set(Hadoop, Spark)
scala> mySet += "Scala" //向mySet中增加新的元素
scala> println(mySet.contains("Scala"))
true
# 声明一个可变集合
scala> import scala.collection.mutable.Set
import scala.collection.mutable.Set
scala> val myMutableSet = Set("Database","BigData")
myMutableSet: scala.collection.mutable.Set[String] = Set(BigData, Database)
scala> myMutableSet += "Cloud Computing"
res0: myMutableSet.type = Set(BigData, Cloud Computing, Database)
scala> println(myMutableSet)
Set(BigData, Cloud Computing, Database)
Map
在Scala中,映射(Map)是一系列键值对的集合,也就是,建立了键和值之间的对应关系。在映射中,所有的值,都可以通过键来获取。Python中对应的是dict(字典)。默认情况下创建的是不可变映射。
val university = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
// university: scala.collection.immutable.Map[String,String]
university("XMU") // String = Xiamen University
如果要定义可变映射,就要导入相关的包。
import scala.collection.mutable.Map
val university2 = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
university2("XMU") = "Ximan University" //更新已有元素的值
university2("FZU") = "Fuzhou University" //添加新元素
循环遍历映射,是经常需要用到的操作,基本格式是:
for ((k,v) <- university) {
printf("Code is : %s and name is: %s\n",k,v)
}
Iterator
迭代器包含两个基本操作:next和hasNext。next可以返回迭代器的下一个元素,hasNext用于检测是否还有下一个元素。有了这两个基本操作,我们就可以顺利地遍历迭代器中的所有元素了。
通常可以通过while循环或者for循环实现对迭代器的遍历。
val iter = Iterator("Hadoop","Spark","Scala")
while (iter.hasNext) {
println(iter.next())
}
函数定义
def sum(a: Int, b: Int, c: Int): Int = a + b + c
定义好sum
之后,如果每次函数里面的一部分参数都是固定的,那每次写起代码来就很冗余。
那么就可以定义一个偏应用函数,固定其中的一部分参数,每次只需要传入剩下不固定的参数即可。
def sum(a: Int, b: Int, c: Int): Int = a + b + c
val sum_a = sum(1, _: Int, _: Int)
sum_a(2, 8) // 返回11
匿名函数
匿名函数,顾名思义就是不需要给函数命名,跟Python的Lambda表达式很类似(感觉就是一个东西)。
(num: Int) => num * 2
val numList = List(-3, -5, 1, 6, 9)
numList.filter(x => x > 0 )
占位符
Scala中有占位符_
,对于之后的每个元素,都会依次传进去。
val numList = List(-3, -5, 1, 6, 9)
numList.filter(_ > 0)
// 返回List[Int] = List(1, 6, 9)
读写文件
Scala本身不像Python有读写文件的语句,而是直接使用Java的文件IO操作。可以参考陈家大少的博客