1、Java与scala之间的共同之处
java与scala都是在jvm之上的语言。都需要编译成.class文件来执行,所以java的class文件scala是可以直接引用。
2、scala基础概念与书写注意事项
2.1 scala基础概念
**对象** - 对象有属性和行为。例如:一只狗的状属性有:颜色,名字,行为有:叫、跑、吃等。对象是一个类的实例。
**类** - 类是对象的抽象,而对象是类的具体实例。
**方法** - 方法描述的基本的行为,一个类可以包含多个方法。
**字段** - 每个对象都有它唯一的实例变量集合,即字段。对象的属性通过给字段赋值来创建。
2.2 scala书写基本注意信息
2.2.1 区分大小写
2.2.2 类名第一个字母大写,多个单词,每个单词首字母大写
2.2.3 方法名称首字母小写,多个单词,第二个单词开始首字母大写
2.2.4 程序文件名:程序文件名称应该与对象名称完全匹配
2.2.5 main(), def main(args: Array[String])--Scala程序从main()方法开始处理,程序入口。
2.3 scala注释方式
2.3.1 /* */ 多行注释
2.3.2 // 单行注释
3、scala基本数据类型
3.1 数据类型介绍
3.1.1 整形
Byte 8位有符号补码整数。数值区间为 -128 到 127
Short 16位有符号补码整数。数值区间为 -32768 到 32767
Int 32位有符号补码整数。数值区间为 -2147483648 到 2147483647
Long 64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807
3.1.2 浮点型
Float 32位IEEE754单精度浮点数
Double 64位IEEE754单精度浮点数
3.1.3 字符型
Char 16位无符号Unicode字符, 区间值为 U+0000 到 U+FFFF
String 字符序列
3.1.4 布尔类型
Boolean true或false
3.2 Scala 基础字面量
3.2.1整形字面量
整型字面量用于 Int 类型,如果表示 Long,可以在数字后面添加 L 或者小写 l 作为后缀。
3.2.2 浮点型字面量
如果浮点数后面有f或者F后缀时,表示这是一个Float类型,否则就是一个Double类型的
3.2.3 布尔型字面量
true false
3.2.4 符号字面量
符号字面量被写成: ‘<标识符> ,这里 <标识符> 可以是任何字母或数字的标识(注意:不能以数字开头)。这种字面量被映射成预定义类scala.Symbol的实例。
如: 符号字面量 ‘x 是表达式 scala.Symbol(“x”) 的简写,符号字面量定义如下:
package scala
final case class Symbol private (name: String) {
override def toString: String = "'" + name
}
3.2.5 字符字面量
在scala中字符类型表示为半角单引号(‘)中的字符:
'\u0041'
'\n'
'\t'
//其中 \ 表示转移字符,其后可以跟 u0041 数字或者 \r\n 等固定的转义字符
3.2.6 字符串字面量
字符串表示方法是在双引号中(“) 包含一系列字符: “Hello,\nWorld!”
3.2.7 多行字符串的标识方法
'''
It is a new language!
Try your best!
'''
3.2.8 scala转义符
4、scala基本语法
4.1 常量、变量的定义
变量:
scala> var a1 = 1
a1: Int = 1
常量:(常量定义赋值后不可改变)
scala> val a2 = 1
a2: Int = 1
同时定义多个变量或者常量:
var age1, age2, age3 : Int = 22
println(age1)
println(age2)
println(age3)
4.2 tab快速补齐
// scala的快捷方式:tab(自动补全,或者跳出可选函数、方法)
scala> aa1.
% & * + -
/ > >= >> >>>
^ asInstanceOf isInstanceOf toByte toChar
toDouble toFloat toInt toLong toShort
toString unary_+ unary_- unary_~ |
4.3 导入库以及函数的使用
导入数学常用函数
scala> import scala.math._
import scala.math._
scala> max(22, 10)
res3: Int = 22
scala> min(9, 2)
res4: Int = 2
4.4 第一个scala程序
object HelloFirst {
def main(args: Array[String]): Unit = {
println("I't s a new world !")
}
}
输出:
I't s a new world !
1 Object是Scala中的一个关键字,相当于java中的public static class这样的修饰符,也就是说Object中的成员都是静态的;
2 例子中的main方法是静态的,不需要实例化就可以被虚拟机调用,作为JVM平台上程序的入口的必备条件;
3 输入main使用快捷方式 ALT + / 可以快速补足main函数;
4 def是scala的关键字,所有使用def定义的内容都是函数或者方法;
5 args:Array[String]其中args是参数名称,Array[String]表面应用程序运行时候传入参数集合;
6 :Unit表明main入口方法的返回类型是Unit,也就是说执行main方法后返回的是Unit类型;
7 Unit是什么类型:相当于java中的Void类型;
8 = 是什么?是表明main方法执行的结果是由谁来赋值的,或者说main方法体在哪?在=的右面;
9 方法体一般使用{}来封装,里面可以有很多条语句;
10 {}语句默认情况下最后一条语句的结果类型就是{}的返回类型;
11 scala的println是借助了java的io操作,也就是说scala调用了java;
12 如果方法或者函数的类型或者返回类型是Unit的话就可以直接省略“:Unit = ”,其他非Unit值不可省略;
13 scala在实现底层经常会使用java的实现来缩短开发时间,例如:操作数据源(DB,NoSQL(HBase))的JDBC,再例如关于线程Thread的操作,scala旺旺也会直接使用java中的Thread;
14 按照当今OS的原理,程序的main入口方法都是运行在主线程中的,os的运行分为Kernel Space和User Space,应用程序是运行在User Space中,应用程序Scala所在的进程一般都是透过OS Fork出来,被Fork出来的应用程序进程默认会有主线程,而我们的main方法就是默认在主线程中的。
4.5 控制语句(if、for、while、break)
4.5.1 if
object Hello1 {
def main(args: Array[String]):Unit = {
println("It\'s My First Scala Project !")
// if控制语句
var age = 20
var result = if (age < 18) "青少年" else "成年"
println(result)
// if表达式可以用在for循环等其他控制结构中用于限制结果
println("if表达式可以用在for循环等其他控制结构中用于限制结果")
for(i <- 0 to 10 if i % 2 == 0) {
println("i = " + i + "可以被2整除!")
}
}
}
输出:
It's My First Scala Project !
成年
if表达式可以用在for循环等其他控制结构中用于限制结果
i = 0可以被2整除!
i = 2可以被2整除!
i = 4可以被2整除!
i = 6可以被2整除!
i = 8可以被2整除!
i = 10可以被2整除!
4.5.2 for
for循环是不断循环一个集合,然后for循环后面{。。。}代码块部分会根据for循环(…)里面提取的集合的item来作为{…}的输入作为流程控制。
2.1 for循环中加入的if叫做条件守卫,用于限制for循环(优化for循环,去掉不必要的执行步骤,或者说用于跳出for循环)
2.2 在for循环中可以提取什么内容取决于集合的类型!
2.3 想跳出for循环的话,除了加入if守卫以外,还可以使用return关键字。
object Hello2 {
def main(args: Array[String]):Unit = {
/* for循环是不断循环一个集合,然后for循环后面{...}代码块部分会根据for循环(...)里面提取的集合的item来作为{...}的输入作为流程控制*/
var result2 = 0
for(i <- 0.to(20)){
result2 = result2 + i
}
println(result2)
// 在for循环中可以提取什么内容取决于集合的类型
for(i <- "Hello, Spark".split(" ")) println(i)
// 想跳出for循环的话,除了加入if守卫以外,还可以使用return关键字
for(i <- 1.to(20)){
if(i == 3) return //return是返回的是方法级别的,这在实际开发中常用
println(i)
}
}
}
输出
210
Hello,
Spark
1
2
4.5.3 while
While循环,也是循环集合来作为{…}的输入,进而完成流程的控制,while循环在实际Server和Framework开发中至关重要,例如一个线程一直继续下去,一般会使用while。
// while循环
var flag = true
for(i <- 1.to(10)){
if(i % 3 == 2) flag = false
while(flag){
println("i = " + i)
flag = false
}
flag = true
}
输出:
i = 1
i = 3
i = 4
i = 6
i = 7
i = 9
i = 10
4.5.4 break
scala中要使用break首先要导入break
import scala.util.control.Breaks._
5、函数
函数暂时可以被简单的认为是包裹了一条或者几条语句的代码体,该代码体接收若干参数,经过代码体处理后返回结果,形成数学中的f(x) = x + 1
关于函数初级入门的几个要点:
* 1、def关键字来定义函数;
* 2、函数会自动进行类型推断来确定函数返回值的类型;如果函数名称和函数体之间没有等于号的话则类型推断失效,此时函数的返回值类型是Unit
* 3、函数的参数可以是类
* 4、如果在函数体中无法推倒出返回值类型,则需要制定返回值类型,例如费波纳茨序列(可能是Int也有可能是Long)
* 5、函数都是有返回值的,没有制定返回值类型的时候默认以最后一行值作为返回值类型;
* 6、默认参数,可以不指定参数,会自动指定一个默认值;
* 7、我们可以基于函数的参数名称来调整传入参数的顺序,重点在于为什么这么做?原因在于函数的背后其实是类,其参数就是类的成员,无所谓顺序;
* 8、函数如果不确定传递参数个数,可以使用变长参数的方式;传参时的一个方便的语法:1L to 5L: _*。
* 9、可变参数中的数据其实是可以被收集为数组Array数组,我们在入口函数main中其实就是可变参数,是以Array[String]的方式呈现的。
object HelloFunctionalProgramming {
def main(args:Array[String]):Unit={
helloWorld("Jerry", 20)
println(helloWorld("Jerry", 20))
// 带名参数,可以指定参数名称,而不需要根据定义的参数的位置进行定义
helloWorld(age = 20, name = "aaa")
println("-*" * 20)
helloWorld2("Tom", 30)
println(helloWorld2("Tom"))
//fibonacci函数的调用
println("fibonacci of 8 : " + fibonacci(8))
// 可变参数调用
println("sumAnyNum : " + sumAnyNum(1, 2, 3, 4, 5))
println("sumAnyNum(1加到5) : " + sumAnyNum(1L to 5L: _*))
println(sumRecursive(1 to 99: _*))
}
//定义一个两个参数函数
def helloWorld(name : String, age : Int): Unit = {
println("Hello, My name is " + name + " !")
println("I'm " + age + " years old!")
}
// age : Int = 30默认参数,可以不传入age,默认赋予age = 30
def helloWorld2(name : String, age : Int = 30) = {
println("Hello, My name is" + name + " !")
println("I'm " + age + " years old!")
age
}
// 费波纳茨序列函数,递归调用
def fibonacci(num : Int) : Long = {
var result = 0
if(num <= 2) 1
else fibonacci(num - 2) + fibonacci(num - 1)
}
// 可变参数
def sumAnyNum(num : Long*) = {
var result = 0L
for(each_num <- num){
result = result.+(each_num)
}
result
}
def sumRecursive(nums : Int*) : Int = {
if(nums.length == 0) 0
else nums.head + sumRecursive(nums.tail: _*)
}
}
输出解析:
// 调用helloWorld("Jerry", 20)
helloWorld("Jerry", 20)
// 调用helloWorld("Jerry", 20) 函数都有返回值,没有指定则会给与一个Unit
println(helloWorld("Jerry", 20))
输出:
Hello, My name is Jerry !
I'm 20 years old!
Hello, My name is Jerry !
I'm 20 years old!
()
// 带名参数,可以指定参数名称,而不需要根据定义的参数的位置进行定义
helloWorld(age = 20, name = "aaa")
输出:
Hello, My name is aaa !
I'm 20 years old!
// 默认参数的调用,可以传入年龄,也可以不传入,默认30
helloWorld2("Tom", 30)
println(helloWorld2("Tom"))
输出:
Hello, My name isTom !
I'm 30 years old!
Hello, My name isTom !
I'm 30 years old!
30
// 因为helloWorld2带有返回值,故会打印出来age 30
//fibonacci递归函数的调用
println("fibonacci of 8 : " + fibonacci(8))
输出:
fibonacci of 8 : 21
// fibonacci的定义中有指定返回值,原因是scala无法无法推倒其返回值,故不指定则会报错。
// 可变参数的调用
println("sumAnyNum : " + sumAnyNum(1, 2, 3, 4, 5))
println("sumAnyNum(1加到5) : " + sumAnyNum(1L to 5L: _*))
println(sumRecursive(1 to 99: _*)) // 递归求和
输出:
sumAnyNum : 15
sumAnyNum(1加到5) : 15
4950