Scala概述

概述

Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各种特性。Scala运行于Java平台(JVM虚拟机),并兼容现有的Java程序

Scala的特点

  • 优雅:这是框架设计师第一个要考虑的问题,框架的用户是应用开发程序员,API是否优雅直接影响用户体验。

  • 速度快:Scala语言表达能力强,一行代码抵得上Java多行,开发速度快;Scala是静态编译的,所以和JRuby,Groovy比起来速度会快很多。

  • 能融合到Hadoop生态圈:Hadoop现在是大数据事实标准,Spark并不是要取代Hadoop,而是要完善Hadoop生态。JVM语言大部分可能会想到Java,但Java做出来的API太丑,或者想实现一个优雅的API太费劲。

编程范式

在这里插入图片描述
Scala是函数式编程,那么函数式编程和命令式编程的不同点是什么?

  • 命令式编程涉及多线程之间的状态共享,需要锁机制实现并发控制

  • 函数式编程不会再多个线程之间共享状态,不需要用锁机制,可以更好的并行处理,充分利用多核CPU并行处理。

跳转顶部


基本输出类型和变量

在这里插入图片描述
在这里插入图片描述
操作符
在这里插入图片描述

  • 操作符的优先级:算数运算符>关系运算符>逻辑运算符>赋值运算符
  • Scala中操作符就是方法:a 方法 b等价于a.方法(b)
        val sum1 = 3 + 5
        val sum2 = (3).+(5)
        println(sum1 == sum2) //true
    
  • 上面是将+看作是一个方法

富包装类型

  • 对于基本数据类型,除了以上提到的各种操作符外,Scala还提供了许多常用运算的方法,只是这些方法不是在基本类里面定义,而是被封装到一个对应的富包装类中

  • 每个基本类型都有一个对应的富包装类,例如Int有一个RichInt类、String有 一个RichString类,这些类位于包scala.runtime

  • 当对一个基本数据类型的对象调用其富包装类提供的方法,Scala会自动通过隐式转换将该对象转换为对应的富包装类型,然后再调用相应的方法。例如: 3 max 5

变量

  • val:不可变的,在声明的时候就必须初始化,并且在初始化之后不可以在赋值
  • var:是可变的,在声明的时候需要进行初始化,但是后面还是可以对值来进行更改的
    //不可变
    val a = 10
    //可变
    var b = "s"
    
  • Scala中由类型推断机制:即根据初始值自动推断变量的类型,使得自定义变量时可以省略具体的数据类型
    跳转顶部

输出输入

从控制台读入数据方法: readIntreadDoublereadBytereadShortreadFloatreadLongreadCharreadBooleanreadLine,分别对应9种基本数据类型,其中前8种方法没有参数,readLine可以不提供参数,也可以带一个字符串参数的提示

所有这些函数都属于对象scala.io.StdIn的方法,使用前必.须导入,或者直接用全称进行调用

在这里插入图片描述
C语言风格格式字符串的printf()函数
在这里插入图片描述
s字符串和f字符串:Scala提供的字符串插值机制,以方便在字符串字面量中直接嵌入变量的值。

基本语法:s " … 变 量 名 … " 或 f " … 变量名… " 或 f " … "f"变量名%格式化字符… "

在这里插入图片描述
Scala需要使用java.io.PrintWriter实现把数据写入到文件,PrintWriter类提供了printprintln两个写方法
在这里插入图片描述
可以使用scala.io.SourcegetLines方法实现对文件中所有行的读取

    val fileInput = Source.fromFile("dataset/test.txt")
    val lines = fileInput.getLines()//得到的是一个迭代器
    for (line <- lines) println(line)

在这里插入图片描述

跳转顶部


控制结构

if条件表达式

if(表达式){
	语句块1
}else if(表达式){
	语句块2
}else{
	语句块3
}

ScalaJava不同的一点就是表达式可以赋值给变量

    var num = 5
    val a = if (num > 4) 1 else -1
    println(a)

while循环的结构,do while循环的特点是,不管是否满足条件,他必定至少执行一次

while(表达式){
	循环体
}
//或者
do{
	循环体
}while(表达式)

跳转顶部


案例演示

    var i = 9
    while (i > 0) {
      i -= 1
      printf("i is %d\n", i)
    }
    var x = 0
    do {
      x += 1
      println(x)
    } while (x < 5)

for循环基本语句

for(变量<-表达式){语句块}

其中变量<-表达式被称为生成器

只有单个生成器的for循环

    //循环输出1-5
    for (i <- 1 to 5) println(i)
    //跳着输出
    for (i <- 1 to 5 by 2) println(i)
    //跳着输出且过滤
    for (i <- 1 to 5 by 2 if i%2==0)println(i)

多个生成器,输出的次数是满足每个生成器的乘积

   for (i <- 1 to 5; j <- 1 to 3) println(i * j)

在这里插入图片描述
for可以直接将循环的值保存在集合中

    var r = for (i <- Array(1, 2, 3, 4, 5) if i % 2 == 0) yield {
      println(i); i
    }
    r.foreach(println(_))

在这里插入图片描述


scala中的breakcontinue

  • 为了提前终止整个循环或者跳到下一个循环,Scala没有breakcontinue关键字

  • Scala提供了一个Breaks类(位于包scala.util.control)。Breaks类有两个方法用于对循环结构进行控制,即breakablebreak

    val array = Array(1, 3, 10, 5, 4)
    breakable {
      for (i <- array) {
        if (i > 5) break
        println(i)
      }
    }
    println("**********************")
    for (i <- array) {
      breakable {
        if (i > 5) break
        println(i)
      }
    }

在这里插入图片描述

数据结构

数组(Array)

数组是一种可变的、可索引的、元素具有相同类型的数据集合
数据的申明如下

    val intValueArr = new Array[Int](3)  //声明一个长度为3的整型数组,每个数组元素初始化为0
    intValueArr(0) = 12 //给第1个数组元素赋值为12
    intValueArr(1) = 45  //给第2个数组元素赋值为45
    intValueArr(2) = 33 //给第3个数组元素赋值为33

    val myStrArr = new Array[String](3) //声明一个长度为3的字符串数组,每个数组元素初始化为null
    myStrArr(0) = "BigData"
    myStrArr(1) = "Hadoop"
    myStrArr(2) = "Spark"
    for (i <- 0 to 2) println(myStrArr(i))

在这里插入图片描述
数组可以不给出类型,Scala会自己根据初始化的数据来推断出数据的类型

	val intValueArr = Array(1,2,3)

多维数组的创建

    //多维数组的创建
    val  myMatrix = Array.ofDim[Int](3,4)  //类型实际就是Array[Array[Int]]
    val  myCube = Array.ofDim[String](3,2,4)  //类型实际是Array[Array[Array[Int]]]
    //访问第一行第二列的元素
    println(myMatrix(0)(1))

元组(Tuple)

元组是对多个不同类型对象的一种简单封装。定义元组最简单的方法就是把多个元素用逗号分开并用圆括号包围起来。使用下划线“_”加上从1开始的索引值,来访问元组的元素

元组的基本定义和使用

    val tuple = ("BigData",2022,2.022)
    println(tuple._1)
    println(tuple._3)

在这里插入图片描述

容器(Collection)

Scala提供了一套丰富的容器(collection)库,包括序列(Sequence)、集合(Set)、映射(Map)等

Scala用了三个包来组织容器类,分别是scala.collectionscala.collection.mutablescala.collection.immutable

scala.collection封装了可变容器和不可变容器的超类或特质,定义了可变容器和不可变容器的一些通用操作

所提供的日期的宏观层次结构
在这里插入图片描述

序列(Sequence)

序列(Sequence): 元素可以按照特定的顺序访问的容器。序列中每个元素均带有一个从0开始计数的固定索引位置

序列容器的根是collection.Seq特质。其具有两个子特质 LinearSeqIndexedSeqLinearSeq序列具有高效的 headtail操作,而IndexedSeq序列具有高效的随机存储操作

实现了特质LinearSeq的常用序列有列表(List)和队列(Queue)。实现了特质IndexedSeq的常用序列有可变数组(ArrayBuffer)和向量(Vector


列表: 一种共享相同类型的不可变的对象序列。定义在scala.collection.immutable包中
不同于Javajava.util.ListscalaList一旦被定义,其值就不能改变,因此声明List时必须初始化

var strList=List("BigData","Hadoop","Spark")

列表有头部和尾部的概念,可以分别使用headtail方法来获取
head返回的是列表第一个元素的值
tail返回的是除第一个元素外的其它值构成的新列表,这体现出列表具有递归的链表结构
strList.head将返回字符串”BigData”strList.tail返回List ("Hadoop","Spark")


构造列表常用的方法是通过在已有列表前端增加元素,使用的操作符为::,例如:

val otherList="Apache"::strList

执行该语句后strList保持不变,而otherList将成为一个新的列表:

List("Apache","BigData","Hadoop","Spark")

Scala还定义了一个空列表对象Nil,借助Nil,可以将多个元素用操作符::串起来初始化一个列表

val intList = 1::2::3::Nil与val intList = List(1,2,3)等效

注意:除了headtail操作是常数时间O(1),其它按索引访问的操作都需要从头开始遍历,因此是线性时间复杂度O(N)。


range

Range是一种特殊的、带索引的不可变的数字等差序列

    //创建1-5的数值序列
    val r = new Range(1,5,1)
    val r1 = 1 to 5
    //1-5且不包含5的序列
    val r2 = 1 until 5
    //1-10,包含终点步长为2的
    val r3 = 1 to 10 by 2
    //创建一个Float类型的数值序列,从0.5f到5.9f,步长为0.3f
    val r4 = 0.5f to 5.9f by 0.3f

在这里插入图片描述

set

集合:元素不重复的容器
列表这元素是按照插入的先后顺序来组织的,但是,集合这元素并不会记录元素的插入顺序,而是以哈希方法对元素的值进行组织,所以,他允许快速第找到某个元素

集合包括可变集合和不可变集合,默认创建的是不可变集合,如需要创建可变集合需要导入scala.collection.mutable.Set

    //不可变
    var mySet = Set("Hadoop","Spark")
    mySet+="Spark"
    println(mySet)
    //可变
    import scala.collection.mutable.Set
    val myMutableSet = Set("Big","Data")
    myMutableSet+="Set"
    println(myMutableSet)

在这里插入图片描述

Map

映射:一系列键值对的容器。键是唯一的,但是值不一定是唯一的。可以根据键来对值进行快速的检索

    val map = Map("name" -> "张三", "id" -> "1", "age" -> "20")
    println(map("name"))

为了给定的键不存在而报错,可以这样

    val name = if (map.contains("name")) map("name") else 0;println(name)

迭代器

迭代器不是一个容器而是提供了按顺序访问容器的数据结构

    val iter = Iterator("Hadoop","Spark","Scala")
    while (iter.hasNext) {
      println(iter.next())
    }

跳转顶部


Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐