Scala基础

一、简介

Scala是一门多范式的编程语言,一种类似java的编程语言 ,设计初衷是实现可伸缩的语言 、并集成面向对象编程和函数式编程的各种特性。

1.发展背景

联邦理工学院洛桑(EPFL)的Martin Odersky于2001年基于Funnel的工作开始设计Scala。随着大数据领域的兴起,由于他的函数式编程的特点,广泛被应用在spark等 编程中

2.说明

  1. 类似于java :Scala源代码(.scala)会被编译成java字节码(.class),然后运行在JVM之上,并可以调用现有的Java类库,实现两种语言的无缝对接 ,大体上和Java的运行模式一样,只不过在编码的时候引进了属于自己 的Scala生态的类库,可以在Java的基础上实现更多的功能
  2. 面向对象 : Scala是面向对象语言,比Java还面向对象。连他的每一个值都是对象
  3. 函数式编程: Scala也是一种函数式语言,其函数也能当成值来使用。支持高阶函数,允许嵌套多层函数,并支持柯里化 。

二、安装 Scala

Scala的安装依赖于Java环境,安装前先安装jdk1.8

1.windows下 安装

  1. 官网下载安装包:scala-2.11.12.msi
  2. 打开cmd窗口输入Scala测试看是否可以使用

2.Linux下 安装

  1. 官网下载安装包:scala-2.11.12.rpm
  2. 将安装包上传到Linux服务器
  3. 解压安装 rpm -ivh scala-2.11.12.rpm
  4. 输入Scala测试

3.IDEA下 安装插件

  1. 进入IDEA—进入设置—进入插件—搜索Scala—点击install----安装后重启
  2. 使用:创建一个新的maven项目
  3. 在创建的项目上右键点击Add Framework Support ,往下滑勾选Scala
  4. 在src/main下创建 Scala文件夹
  5. 点击创建的这个文件夹,右键mark Directory as —> Sources Root
  6. 然后右键就可以看到Scala Class选项了,即可以创建Scala项目了

三、Scala的基础

由于和Java类似,就类比Java来学习就行了

1.变量

  1. 在Scala中声明变量只有两种类型,一种是val 类型,一种是var类型,val类型的变量表示是不可变的,var表示是可变的:赋值以后还可以操作改变他的值。例如:val a1 = 10 在不指定类型的时候,Scala会自动判断值的类型,并使用

2.数据 类型

  1. 在Scala中是完全面向对象的语言,所以并不区分基本类型和引用类型,这些类型都是对象,我们称之为常用类型。
  2. 包括7中数值类型:Byte、Char、Short、Int、Long、Float、Double及Boolean类型,还有String类型。
    在这里插入图片描述

3.数据类型的继承关系

  1. 在Scala中是完全面向对象的语言,所以并不区分基本类型和引用类型,这些类型都是对象,称之为常用类型。
  2. Scala中,所有的值都是类对象,而所有的类,包括值类型,都最终继承自一个统一的根类型Any
  3. any下分为两种类型,一种是引用类型,一种是非引用类型
  4. 三个特殊的 类型1:Null是所有引用类型的子类型。2: Nothing,可以作为没有正常返回值的方法的返回类型。3: Unit类型用来标识过程,也就是没有明确返回值的函数。类似于static
    如图所示:
    在这里插入图片描述

4.值类型转换

  1. 自动类型转化。当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数据类型,这个就是自动 类型转换 。自动提升原则:表达式结果的类型自动提升为操作数中最大的类型。(byte,short)和char之间不会相互自动转换,但是byte,short,char可以自动转换为int类型。byte,short,char他们三者可以计算,在计算时先转换为int类型
  2. 强制类型转换:自动类型转换的逆过程,将容量大的数据类型转换为容量小的数据类型。使用时要加上强制转换函数。例var num:Int = 2.5.toInt
  3. 值类型和String类型的转换:var a2:String = 1 + "" .

4.运算符

  1. 大体和Java一样,只不过不能使用:--、++
  2. 没有三目运算符,使用if实现

5.流程控制

  1. Scala中任意表达式都是有返回值的,也就意味着if else表达式其实是有返回结果的,具体返回结果的值取决于满足条件的代码体的最后一行内容
  2. 如果缺少一个判断,什么都没有返回,但是Scala认为任何表达式都会有值,对于空值,使用Unit类
  3. 三目运算符在Scala中的实现:val result = if (flg) 1 else 0
  4. scala中的模式匹配类似于java中的switch语法,但是更加强大。模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case_分支,类似于java中default语句
  5. for循环:
for (i <- 1 to 10){   	 //前后闭合
	println(i)
}

for (i <- 1 until 10){    //前闭后开
	println(i)
}
  1. 特点:循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过
for (i <- 1 to 10 ; if i%2 ==0){
     println(i)
}
  1. .嵌套循环
for (i <- 1 to 2;j <- 1 to 3){
    println("i="+i+"  j="+j)
}
  1. 循环返回值:将遍历过程中处理的结果返回到一个新Vector集合中,i这里是一个代码块,这就意味我们可以对i进行处理
var res = for(i <- 1 to 10 ) yield i
println(res)
输出结果:  Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
  1. Break & Continue Scala使用函数式风格解决break的功能:1。导入包:import scala.util.control.Breaks
    将需要使用break的代码块使用 Breaks.breakable包括起来,当break时就使用 Breaks.break(),break
Breaks.breakable{
    for(i<- 1 to 9){
        if(i == 5){
          Breaks.break()
        }
        println(i)
	}
}
println("结束")

6.函数

  1. 函数的定义:
def 函数名(参数名1: 参数类型1, 参数名2: 参数类型2) : 返回类型 = {
  函数体
}
  1. 函数的返回值:Scala中的函数可以根据函数体最后一行代码自行推断函数返回值类型。果函数明确声明无返回值(声明Unit)
  2. 函数的参数可以赋默认值:
def f5(p:String = "f5") {
    println(p);
}
  1. 可变长参数 :
def f7(args: Int*) = {
  var result = 0
  for(arg <- args)
    result += arg
  result
}
  1. 惰性函数:当函数被 调用时候才会加载。也叫做懒加载使用lazy 修饰
  2. 内嵌函数:函数内部还可以定义函数:
def main(args: Array[String]): Unit = {
    def test1(): Unit ={
      println("测试")
    }
    test1()
}
  1. 匿名函数。可以被作为一个值赋值给一个变量
val f1 = (v1:Int,v2:Int) => v1+v2
  1. 函数可以作为参数也可以作为返回值
1.作为参数:
def test1(f1:(Int,Int)=>Int,v1:Int,v2:Int)={
    f1(v1,v2)
}
2.作为返回值
def main(args: Array[String]): Unit = {
    val f1: (Int, Int) => Int = test1()
    f1(10,20)
 }

7.类和对象

  1. 定义一个类,类中可以有属性和方法:
class Student {

  var name:String = _

  var age:Int = 0

  def show(): Unit ={
    println(s"$name,$age")
  }

}
  1. 根据这个自定义的类,创建一个对象:val student:Student= new Student()

  2. 构造器。

  class 类名(形参列表){  //主构造器(无参构造器)

   def this(形参列表){   //辅助构造器
   this()//类似于Java中的super(),但Scala中必须写这个,还得放在第一行
   .....
   }
   
   def this(形参列表){   //辅助构造器可以有多个
   this()
   .....
   }
}    


8.封装继承多态、抽象类、接口

  1. 封装 :用private 修饰属性后,生成的setter/getter方法
def setAge(age:Int):Unit={
    if(age > 0 && age < 100){
      this.age = age
    }
  }

def getAge(): Int ={
    
    return age
}
  1. 继承
class 子类名 extends 父类名{ 类体 }

// 重写父类方法需要使用override修饰
override def xxx(): Unit ={
  
}
  1. 多态
var s:Person = new Student
//要测试某个对象是否属于某个给定的类,可以用isInstanceOf方法。
//用asInstanceOf方法将引用转换为子类的引用

if(s.isInstanceOf[Student]){
    val student: Student = s.asInstanceOf[Student]
    student.study()
}
  1. 抽象类:在scala中,通过abstract关键字标记不能被实例化的类。方法不用标记abstract,只要省掉方法体即可
abstract class Person{
  var name:String = _
  def sayHello()
  //def sayHello():Unit = ???
}
  1. 接口 trait
//声明一个特质 trait
trait 特质名{
    trait 体
}
//使用特质
1) 没有父类,可以直接继承特质
class 类名 extends 特质1 with 特质2
2) 有父类
class 类名 extends 父类 with 特质1 with 特质2

9.静态属性和静态方法、伴生对象

  1. 由于Scala没有静态方法,通过object去定义静态方法或者静态对象
  2. 果类和object在一个scala文件中,则称为object User 是class User的伴生对象
//Scala中伴生对象采用object关键字声明,伴生对象中的全是”静态“内容,可以通过伴生对象名称直接调用
//伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致
//伴生对象中的属性和方法都可以伴生对象(类名)直接调用访问
//从语法角度来讲,所谓的伴生对象其实就是类的静态方法和成员的集合
class User{ 
}

object User{  //伴生对象  
}
  1. 伴生对象 apply方法:使用伴生对象可以方便的创建对象,只需要覆盖对应的apply方法,如下:
class User {
  def test2(): Unit ={
    println("test2方法execute")
  }

}

object User{
  def apply(): User = {
    println("11111111")
    new User()
  }
}

测试:
val user = User()   //或者 val user = User.apply()
user.test2()

10.隐式传值和隐式转换

  1. 隐式函数:隐式变量的优先级高于默认值
implicit def f(i:Double):Int = {
	i.toInt	
}
var number:Int = 3.5
println(number)
  1. 隐式变量:隐式变量的优先级高于默认值

implicit def f(i:Double):Int = {
	i.toInt	
}
var number:Int = 3.5
println(number)
  1. 隐式类:(可以给一个已经定义好的方法新增加一些方法或属性)
object Test {
  def main(args: Array[String]): Unit = {
    val yuan = new Yuan
    yuan.one()
    //现在写一个类给原类增加一个方法
    implicit class Zeng(val yuan: Yuan) {
      def two() = {
        println("这是给原始类增加的一个方法")
      }
    }
    //再测试一下,就可以调用刚才新增加的方法了
    yuan.two()

  }
}
class Yuan{
  def one() = {
    println("这是原来的类自己的方法")
  }
}


11.异常

  1. Scala提供try和catch块来处理异常。try块用于包含可疑代码。catch块用于处理try块中发生的异常。可以根据需要在程序中有任意数量的try…catch块。
try {
     val r = 10 / 0
} catch {
     case ex: ArithmeticException=> println("捕获了除数为零的算数异常")
     case ex: Exception => println("捕获了异常")
} finally {
     // 最终要执行的代码
}

11.集合

Scala同时支持不可变集合和可变集合,不可变集合可以安全的并发访问

  1. Array不可变数组
var arr1 = new Array[String](3)
var arr2 = Array(1,2,3)   //省略new,底层通过伴生对象的apply方法构建Array对象

//获取元素
//根据下标获取
arr1(0)
//遍历
for (elem <- arr1) {
    println(elem)
}
//求数组长度
 arr1.size 
  1. ArrayBuffer(可变数组)
var arrayBuffer = new ArrayBuffer[Int]()
//修改
//添加元素
arrayBuffer += 1
arrayBuffer.append(2)
//修改元素  根据下标修改指定位置元素
arrayBuffer(1) = 5
//删除元素  根据下标删除指定位置元素
arrayBuffer.remove(1)
//获取元素
//根据下标获取
arrayBuffer(0)
//遍历
for (elem <- arrayBuffer) {
    println(elem)
 }
arr1.toBuffer   //定长数组转可变数组
arr2.toArray    //可变数组转定长数组

注意: arr1.toBuffer 返回结果才是一个可变数组,arr1本身没有变化
      arr2.toArray  返回结果才是一个定长数组,arr2本身没有变化

  1. Tuple (元组):可以装不同类型的容器
    元组是不可变的,最多可以存储22个元素
val t1 = ("zhangsan",12,"lisi",11.2)
println(t1._1)    //输出:zhangsan
println(t1._2)    //输出:12

for (elem <- t1.productIterator) {
      println(elem)
}

  1. List (不可变列表)
    Scala中的List和Java List不一样,在Java中List是一个接口,真正存放数据是ArrayList,而Scala的List可以直接存方数据。默认情况下scala的List是不可变的,List属于序列Seq。
val list1 = List(1,2,3,4) 
//根据下标获取
list1(0)
+   在list后面追加
+:    在list前面添加


//通过 :++: 给list追加元素(本身list集合并没有变化)
val list2: List[Int] = list1 :+ 10
println(list2)     //输出结果: List(1, 2, 3, 4, 10)

val list3: List[Int] = 20 +: list1
println(list3)    //输出结果: List(20, 1, 2, 3, 4)

//符号::表示向集合(新建)中添加元素
//运算时,集合对象一定要放置在最右边,且运算规则是,从右至左
//:::运算符是将集合中的每一个元素加入到集合中去
val list1 = List(1,2,3,4)
var list5 = 6::7::list1::Nil
//分析过程
//1). List()  2). List(List(1,2,3,4)) 
//3). List(7,List(1,2,3,4))  4). List(6,7,List(1,2,3,4)) 
println(list5)			//输出结果: List(6, 7, List(1, 2, 3, 4))

var list6= 6::7::list1:::Nil
println(list6)			//输出结果: List(6, 7, 1, 2, 3, 4)
  1. ListBuffer (可变列表)
    ListBuffer是可变的list集合,可以添加,删除元素,ListBuffer属于序列
var listBuffer = ListBuffer[Int](1,2,3)
或者
var listBuffer = ListBuffer[Int]

//向集合中添加一个元素
var listBuffer2 = ListBuffer[Int]()
listBuffer2 += 4
listBuffer2.append(5)
println(listBuffer2)			//输出结果: ListBuffer(4, 5)

//向集合中添加另外一个集合
var listBuffer = ListBuffer[Int](1,2,3)
listBuffer ++= listBuffer2
println(listBuffer)			    // 输出结果:ListBuffer(1, 2, 3, 4, 5)

//根据下标移除数据
var listBuffer = ListBuffer[Int](1,2,3)
listBuffer.remove(0)
println(listBuffer)			    // 输出结果:ListBuffer(2, 3)

//根据下边修改数据
var listBuffer = ListBuffer[Int](1,2,3)
listBuffer(0) = 10
println(listBuffer)			    // 输出结果 ListBuffer(10, 2, 3)	


//根据下标获取指定位置的元素
listBuffer(0)  

//遍历
var listBuffer = ListBuffer[Int](1,2,3)
for (elem <- listBuffer) {
      println(elem)
}

  1. Map
val map1 = Map("a1"->"zhangsan","a2"->"lisi")   	   //不可变
println(map1)

val map2 = mutable.Map("a1"->"zhangsan","a2"->"lisi")   //可变
println(map2)

val map3 = new mutable.HashMap[String,String]()         //创建空的Map

val map2 = mutable.Map("a1"->"zhangsan","a2"->"lisi")
//key不存在,执行添加。否则是修改
map2("a3") = "wangwu"
map2.put("a4","zhaoliu")

//创建一个map
val map2 = mutable.Map("a1"->"zhangsan","a2"->"lisi"). map("key")
作用:如果key存在,则返回对应的值
     如果key不存在,则抛出异常[java.util.NoSuchElementException]
	注意:在java中,如果key不存在则返回null
例如:map2("a1")   输出:zhangsan
     map2("x1")   抛出异常

②. map.get("key")
作用:map集合中的get方法会返回Option对象,如果key存在是Some,否则是None
例如:map2.get("a1")   输出:Some(zhangsan)
     map2.get("x1")   输出:None

③. map.get("key").getOrElse([默认值])
作用:如果是Some,getOrElse可以返回key对应的value,否则返回默认值
     如果getOrElase没有给定默认值,则返回() (()是Unit的唯一实例)
例如:map2.get("a1").getOrElse()   输出:zhangsan
     map2.get("x1").getOrElse()   输出:()
     map2.get("x1").getOrElse(null)   输出:null
简写:map2.getOrElse("key",null). map.contains("key")
作用: 判断key是否存在,存在返回true,否则返回false

使用技巧:如果我们确定map有这个key,应当使用map(key)
        如果不能确定,则先使用map.contains(key)判断
        如果只是期望获取一个值,可以使用map.getOrElse(key,默认值)


//删除
方式1:map -= (key,key)   // -= 这种形式可以一次删除多个key-value
方式2:map.remove(key)
注意: 如果key存在则删除,不存在也不会报错


键值对遍历
方式1:k,v是两个变量,接收map遍历获取的key-value
for ((k,v) <- map) {
      println(k +"\t" + v)
}
方式2:elem获取map遍历出的元祖,elem可以通过操作元祖的形式获取key-value
for (elem <- map) {
    println(elem._1 + "\t" + elem._2)
}
键遍历
for (elem <- map.keys) {
      println(elem)
}
值遍历
for (elem <- map.values) {
      println(elem)
}
  1. Set
    Set存储的元素不允许重复,且不保留顺序,默认是以哈希Set实现
import scala.collection.mutable
val set1 = Set(1,3,2)             //不可变
val set2 = mutable.Set(1,3,2)     //可变

//三种向集合添加元素的方式
val set2 = mutable.Set(1,2,3)     //可变
set2.add(4)
set2 += 5

//两种从集合中移出元素的方式
set2 -= 2
set2.remove(3)


for (elem <- set2) {
      println(elem)
}
  1. Option
object Test8_Option {

  def main(args: Array[String]): Unit = {
    //Option 是一个抽象类   它有两个子类  Some () 和  None (没有)
    /**
     * Option
     *       get        作用:获取值
     *       getOrElse  作用: 获取值,获取到直接返回,如果获取不到则返回默认值
     *
     * Some对象 调用get方法可以获取里面存储的值
     *         调用getOrElse(默认值)方法,还是返回Some对象本身存储的值
     *
     * None对象 调用get方法报报错
     *         调用getOrElse(默认值)方法,返回默认值
     */
     var s = Some(1)
     println(s.getOrElse(2))  //输出1

     var s2 = None
     println(s2.getOrElse(2)) //输出2

     val option = test1(2) //如果调用一个方法,返回值是Option类型,你能够保证他的实际类型是Some,那么你就可以调用get方法,否则建议使用getOrElse方法
     println(option.getOrElse("匿名"))
  }

  def test1(i:Int) = {
     if(i == 1){
       Some("张三")
     }else{
       None
     }
  }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值