Scala简介
Scala和java一样 , 是基于JVM的语言 . Scala是面向对象+面向函数编程的语言 .
Scala的特性:
1 . 与java无缝整合 , Scala也是编译成.class文件 , 交给JVM执行的. 所以java可以和Scala互相调用 .
2 . 类型推断机制 , Scala的变量类型是var , 常量类型是val . Scala常用val , 因为JVM的垃圾回收机制可以很好的回收. 所谓类型推断即对于数字字符等类型可以自动推导判断 …
3 . 支持并发和分布式 , Scala语言的通讯模型Actor设计的时候支持多台服务器节点单进程多线程执行任务 .
4 . 特质特性 , Scala既可以使用变量也可以使用常量 , 即支持单继承, 也支持多继承 , 同时也支持单实现和多实现 .
5 . 模式匹配 , Scala的Switch不止可以匹配值, 还可以匹配类型 .
6 . 高阶函数 , 不止是值可以作为参数进行传递 , 方法也可以作为参数被传递 .
Scala语法
数据类型
- val , var(声明, 底层类型如下)
(以上类型声明val,var的时候自动推导,不可像java一样声明)类型 字节数 bit数 取值范围 Byte 1字节 1*8 -128-127 Short 2 2*8 -32769 - 32767 Int 4 4*8 -2147483648 - 2147483647 Long 8 8*8 -9223372036854775808 - 9223372036854775807 Float 4 4*8 单精度浮点数 Doule 8 8*8 双精度浮点数 Char 字母1字节,中文2字节 英文字母:1 * 8,汉字:2 * 8 Unicode字符,范围U+0000 - U+FFFF String 取决于字符长度 取决于字符长度 字符串 Boolean 1 1*8 布尔类型 - Unit表示没有返回值 , 相当于java中的void
- Null表示空值,空引用
- Nothing 所有其他类型的子类型,表示没有值 . 其存在的价值在于自动推导的时候如果无法推导就会返回Nothing .
- Any 在Scala语言中所有类型的父类和超类 , 任何实例都属于Any类型 . 但Any类型不等同于Object , 因为Any类型继承自Object类 .
- AnyRef 所有引用类型的超类 .
- AnyVal 所有值类型的超类 .
scala基本语法
package com.credi
/**
* class是类 , object是对象
* scala中定义的object中的变量,方法都是静态的
* scala语句结束后不必像java一定要以";"结尾, 可写可不写,系统会自动在每一行的结尾补,多行代码写一行的时候一定要写
* class名称和object名称可以相同 , 同名的class是object的伴生类 , 同名的object是class的伴生对象 , 伴生类和伴生对象之间可以互相访问私有变量
* 同一个包下class名称不能和class相同 , object同理
*/
// object不可以传参 , class可以
object Lesson_ObjAndClass { //object中的变量和方法都是静态的! 相当于java中的单例对象
//object person{ //object名称和class名称可以相同 , 同名的class是object的伴生类 , 同名的object是class的伴生对象 , 伴生类和伴生对象之间可以互相访问私有变量
val slogan = "today is good day" //静态属性
def main(args: Array[String]): Unit = { //main方法,程序入口,静态的
//变量
var a = 100 //赋值
// var a: Int = 100 //变量名后跟隐藏类型可强行指定变量类型
a = 10 //重新赋值
print(a+"---------->"); //打印后不换行
//常量
val b = "今天风儿好喧嚣"
// b = "呵呵" //常量赋值后不可更改
println(b) //打印后换行
//创建静态对象
val person = new person("张星彩",18)
println(person.name) //class类不用像java写get,set
person.show() //调用show方法
// println(person.gender) //伴生类和伴生对象之间可以互相访问私有变量
//to操作符
println(1 to 10) //1,2,3....10
println(1 until 10) //1,2,3...9
println(1 to (10,2))//1,3,5,7,9
println(1 until (9,2))//1,3,5,7
//循环控制语句
// 1 .if
val i = 10
if(i<10){
println("小于10")
}else if(i>=10 && i<=20){
println(i);
}else{
println("哈哈..")
}
// 2 . for
for(j<- 1 to 10){ //循环输出1-10 不用声明
print(j + "==>");
for(k<- 20 to 30){ //嵌套循环
print(k+" ");
}
println()
}
println("--------------")
// 2 . 2 for嵌套简化
for(j <- 1 to 10 ; k <- 20 to 30){ // 每遍历一次j的值 , 把k的值全部遍历一次
println("j = " + j + " k = " + k)
}
// 2 . 3 99乘法表
for(i <- 1 to 9){
for(j <- 1 to i){
print(i+" * "+j+" = "+(i*j)+" ")
}
println()
}
// 2 . 4 for和if的综合使用 , i被2整除并且=98
for(i <- 1 to 100 if(i%2==0) if(i==98)){
println(i)
}
// 2 . 5 for循环遍历的结果放到集合中
val result = for(i <- 1 to 10 if(i%10==0)) yield i //yield关键字把符合结果的i值依次放到result集合中
println(result)
// foreach循环遍历
result.foreach(x=>{ //将result集合的每个元素依次赋给x
println(x) //每遍历一个元素,把x的值输出
})
// foreach简化, 如果result只有1个元素 , 可以简化如下
result.foreach(println)
}
}
//class Person{ //class 是scala中的类
class person(xname:String,xage:Int) { //scala的类可以传参 , 不用写构造函数了???
val name = xname
val age = xage
var addr: String = null
private var gender = "girl"
println("类中的println方法"); //new 一个class的时候,除了普通的函数不执行,其他的都会被执行
//def:定义方法的开头关键字
def this(xname: String, xage: Int, xaddr: String) { //构造函数重载
this(xname,xage) //这样调用是必须的
this.addr = xaddr
}
def show()={ //普通函数声明
println("hello scala" +"====" + Lesson_ObjAndClass.slogan)//调用了class类的静态属性
}
}
函数
package com.credi
import java.util.Date
/**
* Created by Administrator on 2019/2/6.
*/
object Lesson_fun {
def main(args: Array[String]): Unit = {
println(fun(5));println() //调用递归函数
println("不给参数:"+fun()+"---给参数:"+fun(1,5)+"---只给一个参数:"+fun(b=100)) //调用带默认值的函数
fun("a","b","c");println() //调用可变参数的函数
fun2('晴','朗') //调用匿名函数
//5 . 偏应用函数
//5.1场景
def showTime(d:Date , log:Char): Unit ={
println("date is " +d+" log is "+log)
}
val date = new Date();
//5.2针对问题 : 以下步骤麻烦
showTime(date,'a')
showTime(date,'b')
showTime(date,'c')
//5.3偏应用函数 , 优化
val fun3 = showTime(date:Date, _: Char) // _类似占位符
fun3('e')
fun3('d')
fun3('f')
//6 . 调用高阶函数
fun6("高阶函数",funTest) // 函数作为参数 , 传函数名即可 , 函数参数值在高阶函数方法块内传递
//6.2 调用高阶函数 , 参数为匿名函数
fun6("高阶函数 ,参数为匿名函数 :" , (i:Int,j:Int)=>{i*j})
//6.3 调用高阶函数 , 返回值为函数
println(fun62("a","b")(1,2)) // 猜测下执行过程
// 7 . 柯里化函数
fun7(1,2)(3) //柯里化函数就是高阶函数的简化版 , 看上去是否与6.3相似
}
//1 . 递归函数
def fun(num:Int) :Int /*递归要显示声明返回类型*/= {
if(num==1){
1 //符合条件返回1
}else{
print(num)
fun(num-1) //否则调用自己
}
}
//2 . 有默认值的函数
def fun(a:Int=2 , b:Int=3):Int ={
a*b
}
//3 . 可变参数和匿名函数
def fun(elems:String*) ={ //*代表可传多个参数 , 将多个参数放入elems集合
// 3.1for循环遍历elems集合
// for(e<-elems){
// print(e)
// }
// 3.2foreach和匿名函数遍历集合
elems.foreach(s=>{ print(s) }) //foreach遍历每个元素, 值赋予s , '=>{}'匿名函数
elems.foreach(print) //可以简化
}
//4 . 匿名函数, 没有方法名的方法
val fun2 = (a:Char, b:Char)=>{ //将2含2个形参的匿名参数赋值给常量fun
println(a+"->"+b)
}
//6 . 高阶函数
/*
* 函数的参数和返回值都可以是函数
*/
def funTest(i: Int,j:Int):Int = {
(i+j)/100
}
def fun6(s:String,f:(Int,Int)=>Int): String ={ //定义参数的时候,定义所传函数的形参和返回值类型
val result = f(100,100) //funTest的参数在这里传
println(s+"-->"+result)
s+"-->"+result //返回值
}
//6 . 2 函数的返回是函数
def fun62(s:String,s2:String):(Int,Int)=>Int ={ //:(Int,Int)=>Int 返回函数的参数和返回值类型
def test(i:Int,j:Int):Int ={
i+j
}
test
}
//7 柯里化函数
def fun7(a:Int,b:Int)(c:Int):Int={
println(a+b+c)
a+b+c
}
}
String字符串,数组容器元组,Trait
package com.credi
import java.io.{BufferedInputStream, FileInputStream, OutputStream}
/**
* Created by Administrator on 2019/2/6.
*/
object Lesson_StrAndArr {
def main(args: Array[String]): Unit = {
// 1 . String字符串
//String
val s = "credi"
val s1 = "Credi"
println(s.equals(s1)) //false
println(s.equalsIgnoreCase(s1)) //true
//StringBuilder
val builder = new StringBuilder
builder.+('a') //追长字符
builder.++=("bc") //追长字符串
builder.append(true) //追加类型
println(builder)
// 2 . 数组容器
//Array 数组
val arr = Array(1,2,3,"4",true) //数组类型 Any
val arr2 = Array[Int](1,2,3,4,5) //Int
val arr3 = new Array[String](3) //String , 长度为3
arr3(2) = "三" // 单个元素赋值
arr.foreach(print) //简单遍历
for(a<-arr3){ //循环遍历
println(a)
}
//List集合 , 有序可重复
val list = List(1,2,3,4,5)
list.foreach(print)
// map方法
val list2 = List[String]("hello yesterday","hello today","hello tomorrow")
val result:List[Array[String]] = list2.map(s=>{s.split(" ")}) //将list2三个字符串元素依次按空格切分 ,形成三个数组
//{"hello yesterday","hello today","hello tomorrow"} --> {[hello , yesterday] , [hello , today] , [hello , tomorrow]}
for(s<-result){
println(s(0))
println(s(1))
}
//flatMap方法
val result2 = list2.flatMap(s=>{s.split(" ")}) //将list2的三个元素按空格直接切成6个字符串
result2.foreach(s=>{
print(s+" ")
})
println("----------------------------------")
//filter
val result3 = list2.filter(s=>{ //filter :过滤 ,接受的参数是boolean , s = false的元素被过滤掉
!s.equals("hello yesterday") //s 等于 "hello yesterday" 返回false , 会被过滤掉
})
result3.foreach(println)
//Set 无序不可重复
val set = Set[Int](1,2,2,3,4,5)
set.foreach(println)
//Map
val map = Map(1->'a' ,(2,'b') , 1->'c') // 1,2是key , b,c是value , key重复会被覆盖
map.foreach(println) // (1,a)会被覆盖
val value = map.get(2) // get方法根据key返回Option , Some代表有值, None代表无值
println(value)
val value2 = map.get(2).get // 在后面再加.get就可以拿到具体的值 , 但是key不存在会报NoSuchElementException
println(value2)
val value3 = map.get(20).getOrElse("xxxx") // 或者加.getOrElse(String) , 如果key不存在 , 会把String参数返回 , 不报异常
println(value3)
//遍历map的key
val keys: Iterable[Int] = map.keys
for(k<-keys){
print(k+" ")
}; println()
//遍历所有的value
val values: Iterable[Char] = map.values
values.foreach(print);println()
// Tuple 元祖 ,scala新增的
val tuple2 = new Tuple2(1,'a') //new 可以省略 , 其实map的每个key,value元素相当于2元祖
println(tuple2.swap) //只有Tuple2有swap方法 , 作用是两个元素调换前后位置
val tuple22 = Tuple22(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,11,1,1,22) //Tuple22最多支持32个
println(tuple22._22) //tuple有toString方法 , ._1-22
val tuple = (1,'g',"b") //Tuple也可以省略
// 遍历Tuple , 和集合数组的遍历不同
val ite: Iterator[Any] = tuple.productIterator
while(ite.hasNext){
println(ite.next())
}
//Trait
val p = new Person("a",17)
val p2 = new Person("a",18)
p.read("p")
p.listen("p")
println(p.isEqual(p2))
println(p.isNotEqual(p2))
}
//4 Trait 类似java抽象类,接口
/*
* Trait 不可以传参 ,支持 多继承(extends ... with ... with ...) 多实现
*/
trait Read{
def read(name:String): Unit ={
println(name+" is read ....")
}
//抽象方法
def isEqual(p:Any):Boolean
def isNotEqual(p:Any): Boolean ={
isEqual(p)
}
}
trait Listen{
def listen(name:String): Unit ={
println(name + " is listen .....")
}
}
class Person(xname:String,xage:Int) extends Read with Listen{ //多继承
//成员属性
val name = xname
val age = xage
def isEqual(p: Any): Boolean ={
//判断两个Person对象的name是否相等
p.isInstanceOf[Person]/*p是不是Person类的对象*/ && p.asInstanceOf[Person]/*将p类型转换为Person*/.name.equals(this.name)
}
}
}
模糊匹配 ,样例类 , Actor通信
- Actor通信,需要向编码器导入jar包:scala-actors.jar
package com.credi
import scala.actors.Actor
/**
* Created by Administrator on 2019/2/6.
*/
object Lesson_Match {
def main(args: Array[String]): Unit = {
//模糊匹配
val tuple = (1,"hello",'a',1.1,true)
val iter = tuple.productIterator
while(iter.hasNext){
val one = iter.next() //遍历tuple元组的每个元素
MatchMethod(one)
}
//样例类
val m1 = new Man("星彩",18)
val m2 = new Man("星彩",18)
println(m1.equals(m2)) //和java一样 , 如果不是样例类, 对象是不会相等的 , 不同对象在堆空间占不同的内存 , 有不同的地址索引
//两台Actor相互通信
val actor1 = new MyActor1()
val actor2 = new MyActor2(actor1)
actor1.start() //启动通信模型
actor2.start()
//actor ! "hello" //发送消息
}
def MatchMethod(o: Any) = {
//1 . 模糊匹配 ,不仅可以匹配值 , 还可以匹配类型 , 匹配的顺序是自上而下匹配 , 匹配成功跳出当次循环
//值得注意的是 ,在匹配过程中会发生值的类型自动转换
o match {
case 1 => println("匹配值 , value=1")
case i:String => println("匹配类型 , 元素的类型的String...") //如果元素的类型是String , 执行方法块 , 元素别名是i
case i:Double => { println("double类型:"+i) }
case _ => println("default...") //模糊匹配 , 什么都匹配不到就输出default...
}
}
}
//2 . 样例类 , 关键词case , 相当于java中重写了equals,hashcode,copy和toString方法的类
case class Man(xname:String,xage:Int){
val name = xname
val age = xage
}
/**
3 . Actor通信模型 , Spark底层节点之间的通信使用的是Akka通信模型 , Akka就是Actor实现的.
Actor相当于我们理解的Thread线程
Actor解决了线程之间锁的问题
*/
class MyActor1 extends Actor{
override def act(): Unit = { //act方法, 接到消息后的处理
while(true){
receive{ //接受消息
case m:Messge => {
if(m.msg.equals("hello1")){
println("收到actor2的消息:"+m.msg)
m.actor ! Messge(this,"hello2") //向2发送消息
}
}
case _=>{ println("default ....")}
}
}
}
}
class MyActor2(actor1:Actor) extends Actor{
actor1 ! Messge(this,"hello1") //自动向actor1发送消息(messge对象) class类对象创建时 ,除一般函数不执行, 其他都执行
override def act(): Unit = { //act方法, 接到消息后的处理
while(true){
receive{ //接受消息
case m:Messge => {
if(m.msg.equals("hello2")){
println("收到actor1的消息:"+m.msg)
m.actor ! Messge(this,"hello1") //向1发送消息
}
}
case _=>{ println("default ....")}
}
}
}
}
//为了让1,2实现相互通信的样例类
case class Messge(actor: Actor,msg:String)