Scala 基础编程

Scala 基础编程

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
  • 打开CMD命令窗口

    C:\Users\DELL>scala
    Welcome to Scala 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_192).
    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_192).
    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 a :Byte =100
a: Byte = 100

scala> var b:Int =12
b: Int = 12

scala> b=a
b: Int = 100

又大到小需要强转

scala> var c:Byte =100
c: Byte = 100

scala> var d:Int =12
d: Int = 12

scala> c=d
<console>:13: error: type mismatch;
 found   : Int
 required: Byte
       c=d

scala> c=d.asInstanceOf[Byte] //强制转换
c: Byte = 12

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

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 = "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 = ()

分支循环

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){
 s"你是少年,你的年龄:${age}"
}else if(age<30){
 s"你是⻘年,你的年龄:${age}"
}else{
 s"你是中年,你的年龄:${age}"
}
println(s"最终结果:$message")

while与do-while

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

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

//while
var i=5 
while (i>0){ 
 println(s"当前i的值:${i}") 
 i = i-1 
 } 
println("~~~~~~~~~~~~~~~~~") 
//do-while
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

匿名函数|方法

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

scala> var sum=(x:Int,y:Int)=> {x+y}
sum: (Int, Int) => Int = <function2>

scala> var multi=(x:Int,y:Int)=> {x*y}
multi: (Int, Int) => Int = <function2>

scala> println(sum(1,2)+" | "+multi(1,2))
3 | 2

def 关键字可以定义一个函数式变量。也可以声明一个标准方法。

def sum(x:Int,y:Int):Int = {
 return x+y 
}
def sum=(x:Int,y:Int)=>x+y
var sum=(x:Int,y:Int)=>x+y
var sum:(Int,Int)=> Int = (x,y)=> x+y
var sum = ((x,y)=> x+y):(Int,Int)=> Int

通过上述变换可以推导出 函数可以转换为变量,因此可以使用var或者val修饰函数式变量,又因为函数式变量是函数,所以可以使用def修饰。

def method(op:(Int,Int)=>Int)(x:Int,y:Int)={
 op(x,y) 
}
val result01 = method((x,y)=>x+y)(1,2)
val result02 = method((x,y)=>x*y)(1,2)
println(result01)
println(result02)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小七_七七

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值