Scala 编程指南-课件版本

本文档是Scala编程的详细指南,涵盖了从环境配置到高级特性的各个方面,包括变量、分支循环、函数、类与对象、隐式转换、集合操作等。特别强调了函数式编程在数据处理中的应用,以及Scala如何与Java集合相互转换。通过对案例的剖析,帮助读者深入理解Scala在实际开发中的应用。

概述

Scala用一种简洁的高级语言将面向对象函数式编程结合在一起。传统业务开发- 领域模型设计(面向对象开发); 大数据开发 - 数据集计算模型-(函数式编程)。函数编程强调的是程序对数据的运行算能力。在面向对象计算数据的时候采取代码不动移动数据.在函数式编程计算的时候数据不动代码动。Scala是一门多范式的编程语言,同时支持面向对象和面向函数编程风格。它以一种优雅的方式解决现实问题。虽然它是强静态类型的编程语言,但是它强大的类型推断能力,使其看起来就像是一个动态编程语言一样。Scala语言最终会被翻译成java字节码文件,可以无缝的和JVM集成,并且可以使用Scala调用java的代码库。除了Scala编程语言自身的特性以外,目前比较流行的Spark计算框架也是使用Scala语言编写。Spark 和 Scala 能够紧密集成,例如 使用Scala语言操作大数据集合的时候,用户可以像是在操作本地数据集那样简单操作Spark上的分布式数据集-RDD(这个概念是Spark 批处理的核心术语),继而简化大数据集的处理难度,简化开发步骤。

编程查询指南:https://docs.scala-lang.org/tour/tour-of-scala.html

环境配置

下载对应的scala版本:https://www.scala-lang.org/download/2.11.12.html

Windows版本安装

  • 点击 scala-2.11.12.msi双击msi文件安装
  • 配置Scala的环境变量SCALA_HOME变量
SCALA_HOME=C:\Program Files (x86)\scala
PATH=C:\Program Files\Java\jdk1.8.0_161/bin;C:\Program Files (x86)\scala/bin;
  • 打开Window窗口
C:\Users\Administrator>scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_161).
Type in expressions for evaluation. Or try :help.

scala>

CentOS安装

  • 下载 scala-2.11.12.rpm
  • 安装配置Scala
[root@CentOS ~]# rpm  -ivh scala-2.11.12.rpm
Preparing...                ########################################### [100%]
   1:scala                  ########################################### [100%]
[root@CentOS ~]# scala
Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_171).
Type in expressions for evaluation. Or try :help.
scala>

IDEA集成Scala开发环境

在File>Setting>Plugins点击 install plugin from disk选项,选择 scala-intellij-bin-2018.2.11.zip安装成功后,重启IDEA。

变量

Scala是一种纯粹的面向对象编程的语言。Scala语言中没有原始数据类型,这一点和Java语言不同,在Scala中一切皆对象。以下是Scala语言中常见类型和类型间的继承关系。

在这里插入图片描述

在Java中常见的基本类型在Scala中都被剔除了,Scala将值类型和引用类型分离。所有的数值变量类型都是 AnyVal的子类,这些变量的值都有字面值。对于一些对象类型的变量都是 AnyRef的子类。对于 AnyRef类下的变量(除String类型),一般不允许直接赋值字面量,都需要借助 new关键创建。

变量声明

Scala语言是一种可以做类型自动推断的强类型的编程语言。变量的类型可通过编译器在编译的时候推断出最终类型。因此Scala中声明一个变量主需要告知编译器该变量的值是常量还是变量,例如:例如声明一个变量使用var即可,如果声明的是一个常量使用val关键字。因此Scala中变量声明的语法如下:

var|val 变量名字[:类型]=变量值[:类型]
scala> var i:Int=1:Int
i: Int = 1

scala> var j=100:Byte
j: Byte = 100

scala> j=i
<console>:13: error: type mismatch;
 found   : Int
 required: Byte
       j=i
         ^

scala> var k=100
k: Int = 100

scala> k=1.0d
<console>:12: error: type mismatch;
 found   : Double(1.0)
 required: Int
       k=1.0d
         ^

Scala虽然可以做类型自动推断,类型一旦确定,不允许更改-强类型编程语言。val表示声明常量。

scala> val i=123
i: Int = 123

scala> i=456
<console>:12: error: reassignment to val
       i=456
        ^

总结:所有AnyVal类型的子类在声明字面值的时候,系统一般都可以自动推断出字面量类型,所以一般情况下可以省略类型的声明。

数值转换-√

数据类型兼容,且由小到大可以直接赋值。

scala> var b:Byte= 100
b: Byte = 100

scala> var i:Int = 12
i: Int = 12

scala> i=b
i: Int = 100

由大到小需要强转

scala> var b:Byte= 100
b: Byte = 100

scala> var i:Int = 12
i: Int = 12

scala> b=i
<console>:13: error: type mismatch;
 found   : Int
 required: Byte
       b=i
         ^

scala> b=i.asInstanceOf[Byte] # 类型强转
b: Byte = 100

scala> var f=1.0f
f: Float = 1.0

scala> var d=2.0d
d: Double = 2.0

scala> d=f
d: Double = 1.0

scala> f=d
<console>:13: error: type mismatch;
 found   : Double
 required: Float
       f=d
         ^

scala> f=d.asInstanceOf[Float]
f: Float = 1.0

注意能够实现数值转换的,要求类型必须是兼容的。

scala> var num="123"
num: String = 123

scala> var i:Int=100
i: Int = 100

scala> i=num
<console>:13: error: type mismatch;
 found   : String
 required: Int
       i=num
         ^

scala> i=num.asInstanceOf[Int]
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
  at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:101)
  ... 32 elided

String转换为AnyVal类型-√

scala> var a="100.5"
a: String = 100.5

scala> var d=1.0D
d: Double = 1.0

scala> d=a.toDouble
d: Double = 100.5

数组

Scala提供了简便的声明和使用数组的方式,例如声明一个Int类型的数组,则使用如下:

scala> var a=Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> var a=new Array[Int](5)
a: Array[Int] = Array(0, 0, 0, 0, 0)

获取数组的值

scala> var a=Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> a(1)
res0: Int = 2

scala> a(0)
res1: Int = 1

scala> a(0)= -1

scala> a
res3: Array[Int] = Array(-1, 2, 3, 4, 5)

scala> a.length
res4: Int = 5

scala> a.size
res5: Int = 5

遍历一个数组

scala> for(i <- 0 until a.length ) println(a(i))
-1
2
3
4
5
scala> a.foreach(item=> println(item)) //细化的
1
2
3
4
5

元组-√

由若干个指定类型的元素 合变量(变量的属性不可更改),称为元组类型。

scala> var a=(1,"zhangsan",true,18)
a: (Int, String, Boolean, Int) = (1,zhangsan,true,18)

scala> a = (2,"lisi",false,19)
a: (Int, String, Boolean, Int) = (2,lisi,false,19)

元组数据访问

scala> a
res1: (Int, String, Boolean, Int) = (2,lisi,false,19)

scala> a._1
res2: Int = 2

scala> a._2
res3: String = lisi

scala> a._2 = "wangwu"
<console>:12: error: reassignment to val
       a._2 = "wangwu"
            ^

元组中元素都是只读的,一般有值类型和String类型构成。在Scala一个Tuple最多能够有22个成员。元组中的元素都是val类型不允许修改(只读),但是元组变量可以修改

Unit类型

Scala中将void作为保留关键字,使用Unit作为void替换品,在Scala中Unit表示什么也没有的对象。因此字面量()

scala> var u=()
u: Unit = ()

scala> 

分支循环

if条件分支

语法

if(条件){
  
}else if(条件){

}
...
else{

}
var age=35

if(age<18){
   
   
  print(s"你是少年,你的年龄:${age}")
}else if(age<30){
   
   
  println(s"你是青年,你的年龄:${age}")
}else{
   
   
  println(s"你是中年,你的年龄:${age}")
}

根据age参数计算msg的取值,可以看出在Scala语法中if分支可以作为变量的赋值语句。可以将分支中返回的结果作为返回值,在利用分支做赋值的时候,不可以给return关键字,系统会自动将代码块最后一行的结果作为返回值。

var message= if(age<18){
   
   
  println("======")
  s"你是少年,你的年龄:${age}"

}else if(age<30){
   
   
  println("++++++")
  s"你是青年,你的年龄:${age}"

}else{
   
   
  println("-----")
  s"你是中年,你的年龄:${age}"
}

println(s"最终结果:$message")

while、do-while

while(条件){
   
   
  //循环体
}

在scala中while和do-while没有continue和break关键字。

 var i=5                     
 while (i>0){
   
                   
   println(s"当前i的值:${i}")    
   i = i-1                   
 }                           
 println("~~~~~~~~~~~~~~~~~")
 i=5                         
 do{
   
                            
   println(s"当前i的值:${i}")    
   i = i-1                   
 }while(i>0)                 

Breaks

Scala 语言中默认是没有 break 语句,但是在 Scala 2.8 版本后可以使用另外一种方式来实现 break 语句。当在循环中使用 break 语句,在执行到该语句时,就会中断循环并执行循环体之后的代码块。

scala> import scala.util.control.Breaks
import scala.util.control.Breaks

scala> var a=10
a: Int = 10

scala>     var break=new Breaks
break: scala.util.control.Breaks = scala.util.control.Breaks@17eeaaf

scala>     break.breakable({
   
   
     |       do{
   
   
     |         print("\t"+a)
     |         a -= 1
     |         if(a<=5){
   
   
     |           break.break()
     |         }
     |       }while(a>0)
     |     })
        10      9       8       7       6

for循环-重点√

  • 迭代遍历数组
scala> var array=Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)

scala> for(item <- array){
   
   print(item+"\t")}
1       2       3       4
  • 通过下标遍历数组
scala> var array=Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)

scala> for(i <- 0 until array.length) {
   
   
     | 		print(array(i))
     | }
  • for可使用多个循环因子
for(i <- 1 to 9){
   
   
      for(j <- 1 to i){
   
   
        print(s"$i * $j = "+(i*j)+"\t")
        if(i==j) println()
      }
    }

scala> for(i <- 1 to 9;j <- 1 to  i){
   
   
     |     print(s"${i}*${j} ="+i*j+"\t")
     |     if(i==j){
   
   
     |         println()
     |     }
     | }

1*1 =1
2*1 =2  2*2 =4
3*1 =3  3*2 =6  3*3 =9
4*1 =4  4*2 =8  4*3 =12 4*4 =16
5*1 =5  5*2 =10 5*3 =15 5*4 =20 5*5 =25
6*1 =6  6*2 =12 6*3 =18 6*4 =24 6*5 =30 6*6 =36
7*1 =7  7*2 =14 7*3 =21 7*4 =28 7*5 =35 7*6 =42 7*7 =49
8*1 =8  8*2 =16 8*3 =24 8*4 =32 8*5 =40 8*6 =48 8*7 =56 8*8 =64
9*1 =9  9*2 =18 9*3 =27 9*4 =36 9*5 =45 9*6 =54 9*7 =63 9*8 =72 9*9 =81
  • for和if的使用
scala> for(i<- 0 to 10;if(i%2==0)){
   
   
     |      print(i+"\t")
     |    }
0       2       4       6       8       10
  • for和yield关键字实现元素的提取,创建子集(重点)
scala> var a=Array(1,2,3,4,5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> var res=for(item<-a) yield item*item
res: Array[Int] = Array(1, 4, 9, 16, 25)

match-case(模式匹配)

在Scala中剔除java中switch-case语句,提供了match-case替代方案,该方案不仅仅可以按照值匹配,还可以按照类型、以及值得结构(数组匹配、元组匹配、case-class匹配等.).

  • 值匹配
var a=Array(1,2,3)
var i=a(new Random().nextInt(3))
var res= i match {
   
   
case 1 => "one"
case 2 => "two"
case 3 => "three"
case default => null
}
println(res)
  • 类型匹配
var a=Array(100,"张三",true,new Date())
var i=a(new Random().nextInt(4))
var res= i match {
   
   
    case x:Int => s"age:${x}"
    case x:String => s"name:${x}"
    case x:Boolean => s"sex:${x}"
    case _ => "啥都不是"
}
println(res)

注意 _表示默认匹配等价default关键字

√函数(方法)

函数声明

def 函数名(参数:参数类型,...):[返回值类型] = {
   
   
    //方法实现
}

标准函数

def sum(x:Int,y:Int):Int = {
   
   
    return x+y
}
或者
def sum02(x:Int,y:Int)= {
   
   
    x+y
}

可以省略return关键字以及返回值类型,系统一般可以自动推断。将代码块最后一行作为返回值。

可变长参数

def sum03(values:Int*)= {
   
   
    var total=0 
    for(i <-values){
   
   
        total+=i
    }
    total
}
def sum04(values:Int*)= {
   
   
    values.sum
}

注意:可变长参数必须放置在最后

命名参数

def sayHello(msg:String,name:String):Unit={
   
   
    println(s"${msg}~ ${name}")
}
sayHello("hello","张三")
sayHello(name="张三",msg="hello")

参数默认值

def sayHello02(msg:String="哈喽",name:String):Unit={
   
   
    println(s"${msg}~ ${name}")
}
def sayHello03(name:String,msg:String="哈喽"):Unit={
   
   
    println(s"${msg}~ ${name}")
}
sayHello02(name="张三")
sayHello03("李四")

内嵌函数

def factorial(x:Int):Int={
   
   
    def mulit(i:Int):Int={
   
   
        if(i>1){
   
   
            i*mulit(i-1)
        }else{
   
   
            1
        }
    }
    mulit(x)
}
println(factorial(5))

√柯里化(Currying)

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。

def sum02(x:Int,y:Int)= {
   
   
    x+y
}
====
def sum04(x:Int)(y:Int):Int= {
   
   
    x+y
}
scala> def sum04(x:Int)(y:Int):Int= {
   
   
     |     x+y
     |   }
sum04: (x: Int)(y: Int)Int

scala> sum04(1)(2)
res41: Int = 3

scala> var s=sum04(1)(_)  # 部分应用函数
s: Int => Int = <function1>

scala> s(2)
res47: Int = 3

scala> var s2=sum04 _ #部分应用函数
s2: Int => (Int => Int) = <function1>

scala> s2(1)
res52: Int => Int = <function1>

scala> s2(1)(2)
res53: Int = 3

√匿名函数|方法

只有参数列表和返回值类型,没有方法名,通常使用匿名函数形式去声明一个函数式变量


                
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值