1、scala
①定义:Scala设计的初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(Java虚拟机),并兼容现有的Java程序。
②特点:优雅、简洁、一行代码抵得上多行Java代码
2、变量和常量、懒值
var r = 1
r = 2;
r = 'A' //这是有问题的,var定义的r是int var rStr: String = "1" //可以在定义的时候指定类型
var a,b = 1 //定义多个变量 val c = 2 //常量
注 :val就不能再赋值了。与之对应的,var可以在它生命周期中被多次赋值
注:官方推荐val 使用val的好处:
1、更安全 2、代码可读性更高 3、资源回收更快,方法执行完,val所定义的变量即回收
注:只有val修饰的变量才能被lazy修饰;使用lazy定义变量后,只有在调用该变量时才会实例化这个变量的值。而且惰性变量只能是不可变变量;
3、包装类(富包装器)
原型 包装类 高级包装 java包装
byte Byte RichByte Byte
short Short RichShort Short
int Int RichInt Integer
long Long RichLong Long
char Char RichChar Character
float Float RichFloat Float
double Double RichDouble Double
boolean Boolean RichBoolean Boolean
BigInt BigInteger //存储大的整数
BigDecimal BigDecimal //存储位数比较多的小数
使用实例:
val valchar: char = 'a'
val valFloat: Float = 1.1F
val valRichLong: RichLong = 1L
注:包装类是为了使基本类型转变为类。而高级包装(富包装器)则是在包装类的基础上扩展了很多其他的方法。
4、继承
Any则是AnyVal, AnyRef的父类。也就是说,Any是所有Scala类型的父类,它内置于Scala内部,由编译器实现。
AnyRef是所有「引用类型」的父(根)类
AnyVal是所有「值类型」的父(根)类
Null类型为所有引用类型的子类,其拥有唯一的实例:null。
Nothing:它是所有类的子类。
5、返回值(Unit、Option)
Unit类型是一个特殊的值类型,它等价于Java中的void。
Option:返回some类型具或NONE,由于有这个特性,在返回值中经常用,防止出现异常
val arr = Array[Int](1,2)
val value1: Option[String] = arr(1)
val value2: Option[String] = arr(3) println(value1) // Some("value1")
println(value2) // None
6、表达式
表达式:一个具有执行结果的代码块,分为条件表达式、块表达式
val y = if (x > 0 ) 1 else -1 //条件表达式 val res = { //块表达式
if (x < 0) {
-1
} else {
"error"
}
}
7、循环
①to、until println(1 to 10 ) //1-10
println(1 until 10 ) //1-9,不打印最后一个数 ②基础循环 for( i <- 1 to 10 ){
println(i)
} ③多层循环 for(i <- 1 to 10; j <- 1 until 10){
println("i="+ i +", j="+j) //当i=1,j循环1-9;当i=2,j循环1-9
} ④加条件循环 for(i<- 1 to 10 ;if (i%2) == 0 ;if (i == 4) ){
println(i) //4,当满足是偶数且i==4才输出
} ⑤yield for( i <- 1 to 10 ) yield{
i * 2 //返回乘以2以后的集合
} ⑥跳出循环 import util.control.Breaks._ breakable(
for(i<-0 until 10) {
if(i==5){
break() //如果i == 5,就终止breakable包裹的这一堆,此时类似于break
}
println(i)
}
) for(i<-0 until 10) {
breakable{
if(i==5){
break() //如果i == 5,就终止breakable包裹的这一堆,此时类似于continue
}
println(i)
}
}
8、函数
①简单函数定义 def fun (a: Int , b: Int ) : Unit = {
println(a+b)
} ②递归函数 def fun(num :Int) :Int= {
if(num ==1)
num
else
num * fun2(num-1)
}
print(fun(5)) //求5的阶乘 ③带默认值的函数 def fun(a :Int = 10,b:Int) = {
println(a+b)
}
fun(b=2) ④可变参数的函数 def fun(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun(1,2,3,4)) ⑤匿名函数 val value2 = ()=>{
println(" ") //无参数匿名函数
} val value3 = (a:Int,b:Int) =>{
a+b //有参数的匿名函数
} ⑥偏应用函数 def log(date :Date, s :String)= {
println("date is "+ date +",log is "+ s)
} val date = new Date() val logWithDate = log(date,_:String) logWithDate("log11") //注:偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。 ⑦生产函数 def mulBy(factor : Double) = (x : Double) => factor * x val quintuple = mulBy(5) //quintuple=(x : Double) => 5* x quintuple(20) // 100 //注:mulBy输入的是一个double类型,返回的是一个匿名函数 ⑧函数柯里化 //将一个函数变为两个函数的顺序调用。比如1+3+4 ,可以分为(1 + 3)+ 4 两个函数 def add(x:Int,y:Int)=x+y <==> def add(x:Int)(y:Int) = x + y //调用:add(1,2)、add(1)(2)
注:方法和函数的区别
①Scala中使用val语句可以定义函数,def语句定义方法
②函数可作为一个参数传入到方法中,而方法不行
③方法转函数:val f1 = m _
9、高阶函数
定义:以函数作为参数或者返回值的函数
①函数作为值 声明:
val f: (String, Int) => Char = _ . charAt (_)
调用:
f("lihaozong",5); ②函数作为参数 声明:
def P(f : (Double) =>Double) = f(0 . 25)
调用:
P( ceil._ ) // 1 . 0 注:函数P的参数是一个函数f(输入、输出都是double),返回值函数f输入为0.25时的输出
10、对象、单例对象、伴生对象
单例对象:scala类的一个实例,使用class创建,但是在单例对象中没有静态方法和静态字段
伴生对象:在Scala的类中,与单例对象类名相同并且用object修饰的对象叫做伴生对象
①apply:当object进行初始化时、集合中取值时候(array(5)、list(1,2,3).foreach等)都要用到
②unapply(提取器):经常用在模式匹配或者偏函数中
注:伴生对象类似于java中的工具类,里面封装的静态成员
11、IO
import scala.io.Source
val source = Source.fromFile("1.txt", "UTF-8")
for (line <- source.getLines) print(line)
12、闭包
定义:函数引用外部变量叫闭包。之所以要单独提出来,因为在分布式计算中,main方法中定义的全局变量,main中的方法不能直接使用Spark的Task调度器会把方法传给Excutor,但不能传递变量。这也是定义广播变量的原因
13、泛型
基础的泛型,此处不讲,主要讲的是比java中多出来的概念。
协变:对类型A和B,A是B的子类型,那么List[A]是List[B]的子类型 def A(animals: List[Animal]): Unit = {....} val cats: List[Cat] = List(Cat("Whiskers"), Cat("Tom")) A(cats) //根据协变List(Cat("Whiskers"), Cat("Tom")为 List[Animal]子类,可以调用 上界: T <: A ,表示类型变量 T 必须是 类型 A 子类 class PetContainer[P <: Pet](p: P) {....} //输入参数p的类型P必须是类型Pet的子类 下界: B >: A 表示参数类型或抽象类型 B 须是类型A的父类 def prepend[U >: B](elem: U): Unit ={...} 上下文界定:T : M, 其中M 必须为泛型类, 必须存在一个M[T]的隐式值 class Pair_Context[T : Ordering](val first: T, val second: T){
def smaller(implicit ord: Ordering[T]) =
if(ord.compare(first, second) < 0) first else second
}