一、Scala简介
Scala是将面向对象和面向函数式整合在一起,基于JVM的编程语言。它由Martin Odersk于2001开发,2004年开始运行在JVM与.Net平台之上,由于其简洁、优雅、类型安全的编程模式而受到关注。
Scala六个特征:
- Java和scala可以无缝混编(因为都是基于JVM的编程语言)
- 类型推测(自动推测类型)
- 并发和分布式(Actor)
- 特质trait,特征(整合java中接口和抽象类的优点)
- 模式匹配(类似于java中的switch)
- 高阶函数(函数的参数是参数,函数的返回是函数)
二、Scala基础
1、数据类型:
Byte、Short、Int、Long、Float、Double、Char、String、Boolean。这些跟JAVA中等同。
- Unit:表示无值,和java中的void等同
- Null:空值或空引用
- Nothing:其他类型的子类,表示没有值
- Any:所有类型的超类,任何实例都属于Any类型,类似于JAVA中的Object
- AnyRef:所有引用类型的超类
- AnyVal:所有值类型的超类
2、变量和常量的声明
变量:用var定义,可修改
常量:用val定义,不可修改
当参数没有修饰,那么外部无法通过对象来调用,类似于JAVA中的private。
var name = "zhangsan"
val gender = "男"
3、类和对象
伴生类:
class Person{
val name = "zhangsan"
val age = 18
def sayName() = {
"my name is "+ name
}
}
伴生对象:
object Lesson_Class {
def main(args: Array[String]): Unit = {
val person = new Person()
println(person.age);
println(person.sayName())
}
}
总结:
- 构造函数和JAVA不一样,直接类名后加参数
- 伴生类中主要声明动态属性,伴生对象主要声明静态属性。
4、if else判断体
- if else
- if else if else
5、循环体
for循环
- 通过索引
- 增强for循环
- 双重循环
- 带有判断条件
- yield
while循环
do while循环
总结:
- yied关键词能够将符合要求的元素自动封装到一个集合中
- 1 to 10包括10,1 until 10不包括10
- scala中不能使用count++,只能使用count = count+1
- 在scala中没有break跳出循环,可设置标记,例如var flag = true
6、函数
1.普通函数(有参函数、无参函数)
def fun (a: Int , b: Int ) : Unit = {
println(a+b)
}
fun(1,1)
def fun1 (a : Int , b : Int)= a+b
println(fun1(1,2))
2.递归函数:在函数体内调用自己本身
// 计算num的阶乘
def fun1(num:Int):Int = {
if(num == 1||num == 0) 1
else num * fun1(num - 1)
}
3.默认值的函数
def fun2(num1:Int = 10,num2:Int = 20) = {
num1 + num2
}
def fun3(num1:Int,num2:Int = 20) = {
num1 + num2
}
def fun4(num1:Int=10,num2:Int) = {
num1 + num2
}
4.可变参数个数的函数
def fun4(elements :Int*)={
var sum = 0;
for(elem <- elements){
sum += elem
}
sum
}
println(fun4(1,2,3,4))
5.匿名函数
var fun6 = (num1:Int,num2:Int) => num1+ num2
6.嵌套函数
def fun7(num:Int)={
def fun8(a:Int,b:Int):Int={
if(a == 1){
b
}else{
fun8(a-1,a*b)
}
}
fun8(num,1)
}
7.偏应用函数
偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。
def log(date:Date,content:String) = {
println("date:" + date + "\tcontent:" + content)
}
val date = new Date()
log(date,"log1")
log(date,"log2")
log(date,"log3")
println("==============================")
val logBoundDate = log(date,_:String)
logBoundDate("log11")
logBoundDate("log12")
logBoundDate("log13")
8.高阶函数
函数的参数是函数,或者函数的返回类型是函数,或者函数的参数和函数的返回类型都是函数的函数。
/**
* 函数的参数是函数:
* f1:(Int)=>Int 告诉要传入的函数的格式
* 把函数当成了对象穿来穿去、scala支持面向函数编程
*/
def highFun1(f1:(Int)=>Int,num:Int) = {
f1(num)
}
def tmpFun(num1:Int) = {
num1+1000
}
/**
* 函数的返回是函数
* 函数无参数
* 函数的返回个(Int,Int)=>Double格式的函数
*/
def highFun2():(Int,Int)=>Double = {
def tmpFun2(num1:Int,num2:Int):Double = {
num1 + num2
}
tmpFun2
}
def highFun3():(Int,Int)=>Double = {
(num1:Int,num2:Int)=>num1+num2
}
/**
* 函数是参数是函数,返回也是函数
* 这个函数也是高阶函数
*/
def highFun4(f1:(Int,Int) => Int,num1:Int):(Int)=>Double = {
val rest = f1(num1,1000)
(num:Int) => num + 1
}
def highFun5(num:Int):(Int)=>Int = {
def fun(a:Int)={
num + a
}
fun
}
9. 柯里化函数
可理解为对高阶函数的简化
def klhFun(a:Int)(b:Int) = a*b
Scala语言的简写规则:
- 函数的返回值类型可以省略,因为scala具备自动推测的功能,他会根据返回值的自动来决定这个函数的返回值类型
- 将你要返回的值放在函数的最后一行,那么这个值就会被自动返回
- 如果你的函数体内只有一个语句,可以将这行语句与函数名在一行。
总结:
- 对于递归函数 必须明确返回值类型,不然不知所措;
- 默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值;如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称;
- 在scala中+=前后的数值类型必须一致,+前后的数值类型可以不一致;
- 注意点:
1)匿名函数不能显示的声明返回值类型
2)匿名函数必须赋给一个变量、变量,通过变量来调用这个匿名函数
3)匿名函数的参数与函数体必须要用=>来关联
7、集合
1.Array
/**
* 创建数组的两种方式:
* 1.new Array[String](3)
* 2.直接Array
*/
//创建类型为Int 长度为3的数组
val arr1 = new Array[Int](3)
//创建String 类型的数组,直接赋值
val arr2 = Array[String]("s100","s200","s300")
//赋值
arr1(0) = 100
arr1(1) = 200
arr1(2) = 300
/**
* 创建二维数组
*/
val secArray = new Array[Array[String]](10)
for(index <- 0 until secArray.length){
secArray(index) = new Array[String](10)
}
/**
* 遍历数组的两种方式
*/
for(i <- arr1){
println(i)
}
arr1.foreach(i => {
println(i)
})
for(s <- arr2){
println(s)
}
arr2.foreach {
x => println(x)
}
2.List
//创建List 不可变List
val list = List(1,2,3,4,5)
//遍历List
list.foreach { x => println(x)}
// list.foreach { println}
// filter方法
val list1 = list.filter { x => x>3 }
list1.foreach { println}
// count方法
val value = list1.count { x => x>3 }
println(value)
// map
val nameList = List(
"hello bjsxt",
"hello xasxt",
"hello shsxt"
)
val mapResult:List[Array[String]] = nameList.map{ x => x.split(" ") }
mapResult.foreach{println}
// flatmap 先map再flat
val flatMapResult : List[String] = nameList.flatMap{ x => x.split(" ") }
flatMapResult.foreach { println }
/**
* 可变的list集合
*/
val listBuffer = new ListBuffer[String]
listBuffer.+=("hello")
listBuffer.+=("bj")
listBuffer.foreach { println }
listBuffer.-=("hello")
3.Set
//创建Set
val set1 = Set(1,2,3,4,4)
val set2 = Set(1,2,5)
//遍历Set集合
//注意:set会自动去重
set1.foreach { println}
for(s <- set1){
println(s)
}
4.Map
val map = Map(
"1" -> "bj",
2 -> "sh",
3 -> "gz"
)
val keys = map.keys
val keyIterator = keys.iterator
while(keyIterator.hasNext){
val key = keyIterator.next()
/**
* map集合的get方法返回值是一个Option类型的对象
* Option类型有两个子类型 分别为some None
*/
println(key + "\t" + map.get(key).get)
}
/**
* getOrElse原理:去集合中去取数据,若不存在返回默认值
*/
println(map.get(4).getOrElse("default"))
// Map遍历
for(k <- map)
println(k._1 + "\t" + k._2)
map.foreach(x=>println(x._1 + "\t" + x._2))
// filter:过滤,留下符合条件的记录
map.filter(x=>{
Integer.parseInt(x._1 + "") >= 2
}).foreach(println)
// count:统计符合条件的记录数
val count = map.count(x=>{
Integer.parseInt(x._1 + "") >= 2
})
println(count)
5.Tuple
/**
* 元组 vs list
* list创建的时候指定了泛型,那么集合中必须是这个泛型的对象
* 元祖中可以包含任意类型的元素,这些元素使用一对小括号来封装
* 元组的创建:最多支持22个
*/
val t2 = Tuple2(1,"hello")
val tt2 = (1,"hello")
val t3 = Tuple3(1,true,"hello")
val tt3 = (1,true,"hello")
val moreTuple = (1,2,3)
// 元组的遍历
val tupleIterator = tt3.productIterator
while(tupleIterator.hasNext){
println(tupleIterator.next())
}
// toString方法
println(tt3.toString())
//swap交换 注意只有二元组对象才会有这个方法
val swapt2 = tt2.swap
println(swapt2._1 + "\t" + swapt2._2)
8、字符串
// String不可变
val str1 = "hello bi"
val str2 = "hello sh"
val flag = str1.equalsIgnoreCase(str2)
println(flag)
str1.split(" ")
// StringBuffer可变
val strBuilder = new StringBuilder
strBuilder.append("hello\t")
strBuilder.append("bj")
println(strBuilder)
总结:
9、Trait特性
Scala相当于JAVA中的接口但是他比接口功能更加强大,与接口不同的是它还可以定义属性和方法的实现。
Trait可以继承多个Trait,也就是多继承,Trait定义的方式与类相似,使用关键字trait。