Scala基础
1.Scala有两种类型的变量:
val:是不可变的,在声明时就必须被初始化,而且初始化以后就不能再赋值;
var:是可变的,声明的时候需要进行初始化,初始化以后还可以再次对其赋值。
基本语法:
val 变量名:数据类型 = 初始值
var 变量名:数据类型 = 初始值
类型推断机制(type inference):根据初始值自动推断变量的类型,使得定义变量时可以省略具体的数据类型及其前面的冒号
定义可简化为:var mystr = "Hello World!"
mystr:String = Hello World!
2.控制台输入输出语句
从控制台读写数据方法:readInt、readDouble、readByte、readShort、readFloat、readLong、readChar readBoolean及readLine,分别对应9种基本数据类型,其中前8种方法没有参数,readLine可以不提供参数,也可以带一个字符串参数的提示
所有这些函数都属于对象scala.io.StdIn的方法,使用前必须导入,或者直接用全称进行调用
向控制台输出信息方法:
print()和println(),可以直接输出字符串或者其它数据类型,其中println在末尾自动换行。
C语言风格格式化字符串的printf()函数printf()可以按照C语言输出格式输出
s字符串和f字符串:Scala提供的字符串插值机制,以方便在字符串字面量中直接嵌入变量的值。
基本语法:s " …$变量名… " 或 f " …$变量名%格式化字符… "
例如:
scala> var i = 10 i:Int = 10 scala> val f = 3.5 f:Double = 3.5452 scala> val s = "hello" s:String = hello scala>println(s"$s:i=$i,f=$f")//s插值字符串 hello:i=10,f=3.5452 scala>println(f"$s:i=$i%-4d,f=$f%.1f") hello:i=10 ,f=3.5
3.写入文件
Scala需要使用java.io.PrintWriter实现把数据写入到文件,PrintWriter类提供了print 和println两个写方法
var out = new PrintWriter("output.txt") for(i <- 1 to 5) out.println(i) out.close()
4.读取文件
可以使用Scala.io.Source的getLines方法实现对文件中所有行的读取
var inputFile = Source.fromFile("output.txt") var lines = inputFile.getLines for(line <- lines) println(line)
5.if条件表达式:基本上与java相同,唯一不同的是,Scala中的if表达式的值可以赋值给变量
var x = 6 var a = if (x>0) 1 else -1
while循环与do while也同java一样
6.for循环
基本语法:for(变量<-表达式)语句块
for(i <- 1 to 5) println(i) 1 2 3 4 5 for(i <-1to 5 by 2) println(i) 1 3 5
“守卫(guard)”的表达式:过滤出一些满足条件的结果。基本语法:
for (变量 <- 表达式 if 条件表达式) 语句块
for(i <- 1 to 5 if i%2==0) println(i) 2 4
Scala也支持“多个生成器”的情形,可以用分号把它们隔开,比如:
for(i <- 1 to 5; j <- 1 to 3) prinfln(i*j)
for结构可以在每次执行的时候创造一个值,然后将包含了所有产生值的集合作为for循环表达式的结果返回,集合的类型由生成器中的集合类型确定。
for (变量 <- 表达式) yield {语句块}
var r = for(i <- Array(1,2,3,4,5) if i%2==0) yield{println(i);i} 2 4 r:Array[Int] = Array(2,4)
7.Scala不支持Java中的“受检查异常”(checked exception),将所有异常都当作“不受检异常”(或称为运行时异常)
Scala仍使用try-catch结构来捕获异常
import java.io.FileReader import java.io.FileNotFoundException import java.io.IOException try { val f = new FileReader("input.txt") // 文件操作 } catch { case ex: FileNotFoundException => // 文件不存在时的操作 case ex: IOException => // 发生I/O错误时的操作 } finally { file.close() // 确保关闭文件 }
为了提前终止整个循环或者跳到下一个循环,Scala没有break和continue关键字。Scala提供了一个Breaks类(位于包scala.util.control)。Breaks类有两个方法用于对循环结构进行控制,即breakable和break:
将需要控制的语句块作为参数放在breakable后面,然后,其内部在某个条件满足时调用break方法,程序将跳出breakable方法。
breakable{ ... if(...) break ... }
8.数组
Scala提供了参数化类型的通用数组类Array[T],其中T可以是任意的Scala类型,可以通过显式指定类型或者通过隐式推断来实例化一个数组。
val intValueArr = new Array[Int](3)//声明一个长度为3的整型数组,每个数组初始值为0 intValueArr(0) = 12 //将第一个值赋值为12 intValueArr(1) = 45 intValueArr(2) = 33
9.元组
元组是对多个不同类型对象的一种简单封装。定义元组最简单的方法就是把多个元素用逗号分开并用圆括号包围起来。
使用下划线“_”加上从1开始的索引值,来访问元组的元素。
如果需要在方法里返回多个不同类型的对象,Scala可以通过返回一个元组实现。
10.序列
序列(Sequence): 元素可以按照特定的顺序访问的容器。序列中每个元素均带有一个从0开始计数的固定索引位置。
序列容器的根是collection.Seq特质。其具有两个子特质 LinearSeq和IndexedSeq。LinearSeq序列具有高效的 head 和 tail 操作,而IndexedSeq序列具有高效的随机存储操作。
实现了特质LinearSeq的常用序列有列表(List)和队列(Queue)。实现了特质IndexedSeq的常用序列有可变数组(ArrayBuffer)和向量(Vector)。
注:所有容器的根为Traverable特质,表示可遍历的,它为所有的容器类定义了抽象的foreach方法,该方法用于对容器元素进行遍历操作。混入Traverable特质的容器类必须给出foreach方法的具体实现。Traverable的下一级为Iterable特质,表示元素可一个个地依次迭代,该特质定义了一个抽象的iterator方法,混入该特质的容器必须实现iterator方法,返回一个迭代器(Iterator),另外,Iterable特质还给出了其从Traverable继承的foreach方法的一个默认实现,即通过迭代器进行遍历。在Iterable下的继承层次包括三个特质,分别是序列(Seq)、映射(Map)和 集合(Set),这三种容器最大的区别是其元素的索引方式,序列是按照从0开始的整数进行索引的,映射是按照键值进行索引的,而集合是没有索引的。
11.列表: 一种共享相同类型的不可变的对象序列。定义在scala.collection.immutable包中
不同于Java的java.util.List,scala的List一旦被定义,其值就不能改变,因此声明List时必须初始化
var strList=List("BigData","Hadoop","Spark")
列表有头部和尾部的概念,可以分别使用head和tail方法来获取
head返回的是列表第一个元素的值
tail返回的是除第一个元素外的其它值构成的新列表,这体现出列表具有递归的链表结构
strList.head将返回字符串”BigData”,strList.tail返回List ("Hadoop","Spark")
不能用new来建立List(原型:sealed abstract class List[+A] )
补充相同类型:对于包括List在内的所有容器类型,如果没有显式指定元素类型,Scala会自动选择所有初始值的最近公共类型来作为元素的类型。因为Scala的所有对象都来自共同的根Any,因此,原则上容器内可以容纳任意不同类型的成员。例如:val x=List(1,3.4,"Spark")
12.序列---Range
Range类:一种特殊的、带索引的不可变数字等差序列。其包含的值为从给定起点按一定步长增长(减小)到指定终点的所有数值。
Range可以支持创建不同数据类型的数值序列,包括Int、Long、Float、Double、Char、BigInt和BigDecimal等
(1)创建一个从1到5的数值序列,包含区间终点5,步长为1 var r = new Range(1,5,1) 1 to 5 (2)创建一个从1到5的数值序列,不包含区间终点5,步长为1 1 until 5 (3)创建一个从1到10的数值序列,包含区间终点10,步长为2 1 to 10 by 2 (4)创建一个Float类型的数值序列,从0.5f到5.9f,步长为0.3f 0.5f to 5.9f by 0.3f
13.集合(Set)
集合(set):不重复元素的容器(collection)。
列表中的元素是按照插入的先后顺序来组织的,但是,“集合”中的元素并不会记录元素的插入顺序,而是以“哈希”方法对元素的值进行组织,所以,它允许你快速地找到某个元素
集合包括可变集和不可变集,分别位于scala.collection.mutable包和scala.collection.immutable包,缺省情况下创建的是不可变集
var mySet = Set("Hadoop","Spark")
mySet += "Scala"
如果要声明一个可变集,则需要提前引入scala.collection.mutable.Set
import scala.collection.mutable.Set val myMutableSet = Set("Database","BigData") myMutableSet += "Cloud Computing"
14.类的定义:
字段用val或var关键字进行定义
方法定义:def 方法名(参数列表):返回结果类型={方法体}
class Counter { var value = 0 def increament(step:Int):Unit = { value += step} def current():Int = { value } }
使用new关键字创建一个类的实例。
var myCounter = new Counter
Scala类中所有成员的默认可见性为公有,任何作用域内都能直接访问公有成员。除了默认的公有可见性,Scala也提供private和protected,其中,private成员只对本类型和嵌套类型可见;protected成员对本类型和其继承类型都可见。
为了避免直接暴露public字段,建议将字段设置为private,对于private字段,Scala采用类似Java中的getter和setter方法,定义了两个成对的方法value和value_=进行读取和修改。
Scala语法中有如下规范,当编译器看到以value和value_=这种成对形式出现的方法时,它允许用户去掉下划线_,而采用类似赋值表达式的形式
15.方法的定义
基本语法:def 方法名(参数列表):返回结果类型={方法体}
方法参数前不能加上val或var,所有的方法参数都是不可变类型。
无参数的方法定义时可以省略括号,这时调用时也不能带有括号;如果定义时带有括号,则调用时可以带括号,也可以不带括号。
方法名后面的圆括号()可以用大括号{}来代替。
如果方法只有一个参数,可以省略点号(.)而采用中缀操作符调用方法。
如果方法体只有一条语句,可以省略方法体两边的大括号
16.特质
Java中提供了接口,允许一个类实现任意数量的接口。
Scala中没有接口的概念,而是提供了“特质(trait)”,它不仅实现了接口的功能,还具备了很多其他的特性
Scala的特质是代码重用的基本单元,可以同时拥有抽象方法和具体方法
Scala中,一个类只能继承自一个超类,却可以实现多个特质,从而重用特质中的方法和字段,实现了多重继承
特质的定义:使用关键字trait。
trait Flyable{ var maxFlyHeight:Int //抽象字段 def fly() //抽象方法 def breathe(){//具体方法 println("I can breathe") } }
特质既可以包含抽象成员,也可以包含非抽象成员。包含抽象成员时,也不需要abstract关键字。
特质可以使用extends继承其它的特质,并且还可以继承类。
特质的定义体就相当于主构造器,与类不同的是,不能给特质的主构造器提供参数列表,而且也不能为特质定义辅助构造器。