····················Scala·······································
1、Scala具有“类型推断”能力,可以自动推断出变量的类型。并输出
2、println()
3、大小写敏感
4、new关键字来生成对象
5、
Scala中的单行注释和多行注释和Java一样。例如: /* * 我是多行注释 * */6、完整定义一个函数
def 函数名 (参数:参数类型,参数:参数类型):返回值类型= { }
----------------------------------
1、一个 val 变量,一旦初始化以后,就不能再次赋值,否则会报错。除非前面加 val 再初始化一次。
2、如果一些变量,需要在初始化以后还要不断修改它的值(比如商品价格),则需要声明为 var 变量。
3、比如,我们要输入表达式val myStr4 = "Hello World!",我们只在命令提示符后面输入“val myStr4 = ”然后就回车,只要Scala解释器推断出你的代码还没有结束,应该延续到下一行,解释器就会在下一行显示一个竖线 “ | ”,你可以继续输入剩余的代码。
4、Int的全名是scala.Int。对于字符串,Scala用java.lang.String类来表示字符串。
5、5.toString() #将 5 变成字符串"5"
6、 intersect方法找出两个字符串的相同字符。 “abc”.intersect(“bcd”) 输出 “bc”
7、在Scala中并没有提供++和--操作符,当需要递增和递减时,可以采用 i+=1
8、求和:val sum=(a).+(b) 或val sum=2+3
9、var a = v1 to 5 var b = 1.to(5) print(),都输出:Range(1,2,3,4,5)
创建一个从1到5的数值序列,不包含区间终点5,步长为1 : 1 until 5 Range(1,2,3,4)
创建一个从1到10的数值序列,包含区间终点10,步长为2: 1 to 10 by 2
创建一个Float类型的数值序列,从0.5f到5.9f,步长为0.3f :0.5f to 5.9f by 0.3f
10、格式化字符串的printf函数,带有调用一行字符串用 printf
如果要每次打印后追加一个换行符,实现换行的效果,就要采用println语句
11、yield关键字,对过滤后的结果构建一个集合。
scala> for (i <- 1 to 5 if i%2==0) yield i // Vector(2,4)
---------数组
1、注意的是,在Scala中,对数组元素的应用,是使用圆括号,而不是方括号,也就是使用intValueArr(0),而不是intValueArr[0],这个和Java是不同的。
2、Scala提供了简洁的数组声明和初始化方法,如下:
val intValueArr = Array(12,45,33) //声明一个长度为3的整形数组
val myStrArr = Array("BigData","Hadoop","Spark") //长度为3的字符串数组
———列表
3、使用 :: 操作,在列表的头部增加新的元素,得到一个新的列表,如下:
val intList = List(1,2,3) //列表
val intListOther = 0::intList
注意,上面操作执行后,intList不会发生变化,依然是List(1,2,3),intListOther是一个新的列表List(0,1,2,3)
4、 :: 操作符是右结合的。如果要构建一个列表List(1,2,3),实际上也可以采用下面的方式:val intList = 3::2::1::Nil
上面代码中,Nil表示空列表。
5、也可以使用:::操作符对不同的列表进行连接得到新的列表,比如:
val intList1 = List(1,2)
val intList2 = List(3,4)
val intList3 = intList1:::intList2
6、实现求和,可以直接调用 sum 方法,如下:
intList.sum 数组也可以
---------元组
7、元组是不同类型的值的聚集。元组和列表不同,列表中各个元素必须是相同类型,而元组可以包含不同类型的元素。
——-集合
- scala> val tuple = ("BigData",2015,45.0)
- tuple: (String, Int, Double) = (BigData,2015,45.0) //这行是Scala解释器返回的执行结果
- scala> println(tuple._1)
- BigData
- scala> println(tuple._2)
- 2015
- scala> println(tuple._3)
- 45.0
8、集(set)是不重复元素的集合。列表中的元素是按照插入的先后顺序来组织的。分可变集和不可变集。
9、创建不可变集用 val
scala> var mySet = Set("Hadoop","Spark")
mySet: scala.collection.immutable.Set[String] = Set(Hadoop, Spark)
scala> mySet += "Scala" //向mySet中增加新的元素 mySet+="1" 报错:type mismatch
scala> println(mySet.contains("Scala"))
true
10、可变集用 var,使用 += 不会出错
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)
11、注意:虽然可变集和不可变集都有添加或删除元素的操作,但是,二者有很大的区别。对不可变集进行操作,会产生一个新的集,原来的集并不会发生变化。 而对可变集进行操作,改变的是该集本身,
--------------映射 Map
12、创建一个不可变映射:
val university = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
println(university("XMU")) //获取映射中的值,可以通过键来获取,可以获得值 Xiamen University
13、可变映射 可修改
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" //添加新元素
也可以使用 += 操作来添加新的元素,如下:
university2 + = ("TJU"->"Tianjin University") //添加一个新元素
university2 + = ("SDU"->"Shandong University","WHU"->"Wuhan University") //同时添加两个新元素
14、输出键值对
for ((k,v) <- university) printf("Code is : %s and name is: %s\n",k,v)
15、分别打印出键、值
for (k<-university.keys) println(k)
for (v<-university.values) println(v)
-----------迭代器
迭代器包含两个基本操作:next 和 hasNext。next 可以返回迭代器的下一个元素,hasNext 用于检测是否还有下一个元素。
16、while循环如下:
val iter = Iterator("Hadoop","Spark","Scala")
while (iter.hasNext) {
println(iter.next())
}
17、for循环如下:
val iter = Iterator("Hadoop","Spark","Scala")
for (elem <- iter) {
println(elem)
}
---------类
class 创建类、object创建对象
18、们把value字段设置为private,这样它就成为私有字段,外界无法访问,如果字段前面什么修饰符都没有,就默认是public,外部可以访问该字段。对于类而言,我们并不需要声明为public,Scala文件中包含的多个类之间,都是彼此可见的。。current()方法里面只有一条语句“value”,那么,value的值就是该方法的返回值。
返回1。increment()方法只是对value的值进行了增加1的操作,并没有返回任何值,所以,返回值类型是Unit。Unit后面的等号和大括号后面,包含了该方法要执行的具体操作语句。如果大括号里面只有一行语句,那么也可以直接去掉大括号;或者,还可以去掉返回值类型和等号,只保留大括号 def increment() {value+=1}class Counter { private var value = 0 def increment(): Unit = { value += 1} def current(): Int = {value} }
val myCounter = new Counter myCounter.increment() //不要括号也可以println(myCounter.current)//新建对象,并调用其中的方法
把TestCounter.scala编译为JVM字节码,那么,可以使用下面命令:
在上面代码中,-Xscript后面跟着的名称Upper1是你自己定义的main类名称,你愿意起个名字叫Upper2,也是可以的。
- scalac -Xscript Upper1 TestCounter.scala //编译
- scala -classpath . Upper1 //执行
19、同一内容,用 main 函数实现上面的操作
class Counter {
private var value = 0
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
}
object MyCounter{
def main(args:Array[String]){
val myCounter = new Counter
myCounter.increment(5) //这里设置步长为5,每次增加5
println(myCounter.current)
}
}
保存后退出vim编辑器。然后,使用scalac命令编译这个代码文件,并用scala命令执行,如下:
采用上面介绍的方法,编译执行这个文件,就可以得到执行结果是5。
- scalac TestCounterJVM.scala
- scala -classpath . MyCounter //MyCounter是包含main方法的对象名称,这里不能使用文件名称TestCounterJVM
20、getter和setter方法
value变成私有字段以后,Scala又没有提供getter和setter方法,怎么可以访问value字段呢?解决方案是,在Scala中,可以通过定义类似getter和setter的方法,分别叫做value和value_=,如:
class Counter {
private var privateValue = 0 //变成私有字段,并且修改字段名称
def value = privateValue //定义一个方法,方法的名称就是原来我们想要的字段的名称
def value_=(newValue: Int){
if (newValue > 0) privateValue = newValue //只有提供的新值是正数,才允许修改
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
}
object MyCounter{
def main(args:Array[String]){
val myCounter = new Counter
println(myCounter.value) //打印value的初始值
myCounter.value = 3 //为value设置新的值
println(myCounter.value) //打印value的新值
myCounter.increment(1) //这里设置步长为1,每次增加1
println(myCounter.current)
}
}
编译执行这个文件,就可以得到三行执行结果,第一行是0,第二行是3,第三行是4。
21、构造辅助器
(1) Scala构造器包含1个主构造器和若干个(0个或多个)辅助构造器。
辅助构造器的名称为this,每个辅助构造器都必须调用一个此前已经定义的辅助构造器或主构造器。下面定义一个带有辅助构造器的类,我们对上面的Counter类定义进行修改:
class Counter {
private var value = 0 //value用来存储计数器的起始值
private var name = "" //表示计数器的名称
private var mode = 1 //mode用来表示计数器类型(比如,1表示步数计数器,2表示时间计数器)
def this(name: String){ //第一个辅助构造器
this() //调用主构造器
this.name = name
}
def this (name: String, mode: Int){ //第二个辅助构造器
this(name) //调用前一个辅助构造器
this.mode = mode
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)}
}
object MyCounter{
def main(args:Array[String]){
val myCounter1 = new Counter //主构造器
val myCounter2 = new Counter("Runner") //第一个辅助构造器,计数器的名称设置为Runner,用来计算跑步步数
val myCounter3 = new Counter("Timer",2) //第二个辅助构造器,计数器的名称设置为Timer,用来计算秒数
myCounter1.info //显示计数器信息
myCounter1.increment(1) //设置步长
printf("Current Value is: %d\n",myCounter1.current) //显示计数器当前值
myCounter2.info //显示计数器信息
myCounter2.increment(2) //设置步长
printf("Current Value is: %d\n",myCounter2.current) //显示计数器当前值
myCounter3.info //显示计数器信息
myCounter3.increment(3) //设置步长
printf("Current Value is: %d\n",myCounter3.current) //显示计数器当前值
}
}
编译执行上述代码后,得到如下结果:
Name: and mode is 1
Current Value is: 1
Name:Runner and mode is 1
Current Value is: 2
Name:Timer and mode is 2
Current Value is: 3
(2)Scala的主构造器是整个类体,需要在类名称后面罗列出构造器所需的所有参数,这些参数被编译成字段,字段的值就是创建对象时传入的参数的值。
class Counter(val name: String, val mode: Int) {
private var value = 0 //value用来存储计数器的起始值
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf("Name:%s and mode is %d\n",name,mode)}
}
object MyCounter{
def main(args:Array[String]){
val myCounter = new Counter("Timer",2)
myCounter.info //显示计数器信息
myCounter.increment(1) //设置步长
printf("Current Value is: %d\n",myCounter.current) //显示计数器当前值
}
}
编译执行上述代码后,得到如下结果:
Name:Timer and mode is 2
Current Value is: 1
-----------对象
详细见厦门数据库实验室
1、scala 可以采用 object 关键字实现单例对象,具备和Java静态方法同样的功能。
2、注意,对于一个Scala应用程序而言,必须包含main方法,如果代码中没有包含main方法,因此,不能使用scalac命令进行编译,而是直接使用scala命令运行代码,就可以得到结果;如果使用scalac命令去编译test.scala文件,就会报错。
3、在Java中,我们经常需要用到同时包含实例方法和静态方法的类,在Scala中可以通过伴生对象来实现。当单例对象与某个类具有相同的名称时,它被称为这个类的“伴生对象”。类和它的伴生对象必须存在于同一个文件中,而且可以相互访问私有成员(字段和方法)。
4、Scala源代码编译后都会变成JVM字节码,实际上,在编译上面的源代码文件以后,在Scala里面的class和object在Java层面都会被合二为一,class里面的成员成了实例成员,object成员成了static成员。
5、反编译 javap Person
6
object HelloWorld {
def main(args: Array[String]){
println("Hello, World!")
}
}
为了运行上述代码,我们现在可以使用两种不同的方法。
第一种方法:直接使用scala命令运行得到结果。
因为这段代码中没有定义类,就是一个单例对象,因此,可以不用编译,直接使用scala命令运行得到结果,命令如下:
scala test.scala
第二种方法:先编译再执行
可以首先使用scalac编译命令对test.scala进行编译,然后,使用scala命令运行,具体如下:
scalac test.scala
scala -classpath HelloWorld
------------应用程序对象 apply、update
7、apply调用
class TestApplyClass {
def apply(param: String): String = {
println("apply method called, parameter is: " + param)
"Hello World!"
}
}
val myObject = new TestApplyClass
println(myObject("param1"))
然后,在Linux系统的Shell命令提示符下运行scala命令:scala test.scala
apply method is called, parameter is:param1
Hello World!
8、对一个数组
val myStrArr = new Array[String](3)
或者
val myStrArr=Array("Big","App","Hadoop")
for ( i <- 0 to 2 ) println( myStrArr( i ) ) //输出
更新其中的某个值:
myStrArr.update(0,"Spark") //将第一个值改为“Spark”
---------------继承
1、抽象类
以汽车为例子,首先我们创建一个抽象类,让这个抽象类被其他类继承。
abstract class Car{ //是抽象类,不能直接被实例化
val carBrand: String //字段没有初始化值,就是一个抽象字段
def info() //抽象方法,不需要使用abstract关键字
def greeting() {println("Welcome to my car!")}
}
关于上面的定义,说明几点:
(1)定义一个抽象类,需要使用关键字abstract。
(2)定义一个抽象类的抽象方法,也不需要关键字abstract,只要把方法体空着,不写方法体就可以。
(3)抽象类中定义的字段,只要没有给出初始化值,就表示是一个抽象字段,但是,抽象字段必须要声明类型,比如:val carBrand: String,就把carBrand声明为字符串类型,这个时候,不能省略类型,否则编译会报错。
--------------特质
特质的定义和类的定义非常相似,有区别的是,特质定义使用关键字trait。
trait CarId{
var id: Int
def currentId(): Int //定义了一个抽象方法
}
上面定义了一个特质,里面包含一个抽象字段id和抽象方法currentId。注意,抽象方法不需要使用abstract关键字,特质中没有方法体的方法,默认就是抽象方法。
特质可混入类中,用 with