大数据开发成长之路——Scala程序设计(一)

Scala基础

简介

Scala是运行在 JVM 上的多范式编程语言,同时支持面向对象面向函数编程,随着SparkKafka这样基于Scala的大数据框架的兴起,Scala逐步成为大数据行业编程的首选。
Scala的优势主要是:

  • 开发大数据应用程序(Spark程序、Flink程序)
  • 表达能力强,一行代码抵得上Java多行,开发速度快
  • 兼容Java,可以访问庞大的Java类库

环境

  • Scala程序运行在JVM之上,所以必须要有Java运行环境,Scala才能正确执行
  1. 安装JDK 1.8 版本,并配置好环境变量,注意:版本一定是JDK8,虽然现在已经到了JDK13

Java SE 8就是Java8,或者jdk1.8

  1. 下载Scala SDK,并配置环境变量
  2. 编译器仍然使用IDEA,需要安装Scala插件

插件在官网下载,要对应你的IDEA版本
插件的安装:【settings——plugins——Install Plugin From Disk】选择下载的压缩包即可!

  1. 使用IDEA新建工程,选择scala
    在这里插入图片描述

语法

变量声明

val/var 变量名称:变量类型 = 初始值

  • val定义的是不可重新赋值的变量(值不可修改)
  • var定义的是可重新赋值的变量(值可以修改)
  • 如果变量类型不显式声明则会自行推断
  • scala的语句最后不需要添加分号

惰性变量

  • scala中使用关键字lazy来定义惰性变量,实现延迟加载(懒加载)
  • 惰性变量只能是不可变变量,并且只有在调用时,才会去实例化这个变量

数据类型

基础类型 类型说明
Byte 8位带符号整数
Short 16位带符号整数
Int 32位带符号整数
Long 64位带符号整数
Char 16位无符号Unicode字符
String Char类型的序列(字符串)
Float 32位单精度浮点数
Double 64位双精度浮点数
Boolean true或false
  • scala中所有的类型都使用大写字母开头
  • 类型说明:
类型 说明
Any 所有类型的父类,,它有两个子类AnyRef与AnyVal
AnyVal 所有数值类型的父类
AnyRef 所有对象类型(引用类型)的父类
Unit 表示空,Unit是AnyVal的子类,它只有一个的实例(),它类似于Java中的void,但scala要比Java更加面向对象
Null Null是AnyRef的子类,也就是说它是所有引用类型的子类。它的实例是null, 可以将null赋值给任何对象类型
Nothing 所有类型的子类不能直接创建该类型实例,某个方法抛出异常时,返回的就是Nothing类型,因为Nothing是所有类的子类,那么它可以赋值为任何类型

在这里插入图片描述

条件表达式

  • scala中的表达式都是有值的,可以理解为表达式是scala中的常用单元或“数据类型”
	val x =1
    val z = if(x>1) 1 else "error"
    print(z)  // error

块表达式

  • 块表达式也是有值的
	val result = {
	    val x=0
	    val y = x+10
	    val z = y+"-hello"
	    val m = z+"-kaikeba"
	    "over"		// 最后的over赋给result
  	}

for循环

  • 和go语言的语法很相似
	val nums= 1 to 10
    for(i <- nums) println(i)
	// 双重for循环
    for(i <- 1 to 3; j <- 1 to 3) println(i*10+j)
	// 乘法表
	for(i <- 1 to 9; j <- 1 to i){
	    print(i+"*"+j+"="+i*j+"\t")
	     if(i==j){
	       println()
	    }    
	}
  • 守卫:for循环中的if判断
	for(i <- 1 to 10 if i >5) println(i)
  • 推导式:使用yield的for表达式,可以构建出一个集合
	val v = for(i <- 1 to 5) yield i * 10
    println(v)  // Vector(10, 20, 30, 40, 50)

方法

def methodName (参数名:参数类型, 参数名:参数类型) : [return type] = {
// 方法体
}

  • 参数列表的参数类型不能省略
  • 返回值类型可以省略,根据方法体的最后一行值确定
  • 在定义方法时可以给参数定义一个默认值
  • 调用方法时,可以指定参数的名称传值
	def add(a:Int,b:Int) = {
    	a+b
    	"value"
  	}
  	print(add(1,2))	// value
  • 如果定义递归方法,不能省略返回值类型
	def m1(x:Int):Int={
	    if (x==1) 1
	    else x*m1(x-1)
	}
	print(m1(10))	// 3628800
  • 变长参数:
	def add(num:Int*) = num.sum
	print(add(1,2,3,4)) // 10

函数

  • scala支持函数式编程,编写Spark/Flink程序会大量使用到函数

val 函数变量名 = (参数名:参数类型, 参数名:参数类型…) => 函数体

  • 函数是一个对象(变量)
  • 一个函数没有赋予一个变量,则称为匿名函数
  • 无需指定返回值类型
	val add = (x:Int, y:Int) => x + y
  	print(add(2,3)) 

数组

  • scala中,有两种数组,一种是定长数组,另一种是变长数组
  • 定长数组

// 通过指定长度定义数组
val/var 变量名 = new Array[元素类型](数组长度)

// 用元素直接初始化数组
val/var 变量名 = Array(元素1, 元素2, 元素3…)

	val a = new Array[Int](10)  // 长度为10的数组
    a(0) = 666
    print(a(0)) // 0

    val b = Array("hadoop","spark","hive") // 初始化
    print(b.length) // 3
  • 变长数组

创建变长数组,需要提前导入ArrayBuffer类:
import scala.collection.mutable.ArrayBuffer

  1. 使用+=添加元素
  2. 使用-=删除元素
  3. 使用++=追加一个数组到变长数组
	var c = ArrayBuffer[Int](666,888)
    c += 999  // 追加
    c -= 888  // 删除
    c ++= a   // 追加一个变长数组
    print(c)  // ArrayBuffer(666, 999, 666, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  • 遍历数组
	for(i <- a)println(i)
	for(i <- 0 to a.length -1 )println(a(i))	
	for(i <- 0 to a.length -1 )println(a(i))	// 0 until n ——生成一系列的数字,包含0,不包含n
  • 数组常见操作
  1. 求和——sum方法
  2. 求最大值——max方法
  3. 求最小值——min方法
  4. 排序——sorted方法
	array.sum
	array.max
	array.min
	array.sorted
	array.sorted.reverse

元组

  • 元组可以用来包含一组不同类型的值

val/var 元组变量名称 = (元素1, 元素2, 元素3…)
val/var 元组变量名称 = 元素1->元素2 // 只有两个元素时

	val a = (1, "张三", 20, "北京市") 
	val b = 1->2 
	// 访问元组中的元素_1、_2、_3....
	print(a._1)	// 1

Map

  • Map可以称之为映射。它是由键值对组成的集合,scala当中的Map集合与java当中的Map类似

val/var map = Map(键->值, 键->值, 键->值…) // 推荐,可读性更好

  • 不可变Map:
	val map1 = Map("zhangsan"->30, "lisi"->40) 
	print(map1("zhangsan"))	// 30
	println(map1.getOrElse("wangwu", -1))	// 如果没有key,返回-1而不是保错
  • 可变Map
	import scala.collection.mutable.Map	// 需要导包,语法相同
	map1("zhangsan") = 50
	map3 += ("wangwu" ->35) // 添加key-value
	map3 -= "wangwu"		// 删除key-value
	println(map3.keys)    // Set(zhangsan, wangwu)
    println(map3.keySet)  // Set(zhangsan, wangwu)
    println(map3.values)  // HashMap(50, 40)
    // 遍历
    for((k,v) <- map3) println(k+" -> "+v)

Set

  • Set是代表没有重复元素的集合
  • Set没有顺序
  • 不可变集合

//创建一个空的不可变集
val/var 变量名 = Set[类型]()

//给定元素来创建一个不可变集
val/var 变量名 = Set[类型](元素1, 元素2, 元素3…)

  • 可变集合

必须导入:import scala.collection.mutable.Set
创建方法和不可变集合相同

	val set = Set(1,1,2,3,4,5)
    println(set.size)
    for(i <- set) println(i)
    set += 6   		 //添加元素
    set += (6,7,8,9) // 添加多个元素
    println(set)
    set -= 1   		// 删除一个元素
    set -= (9,10)   // 删除多个元素
    println(set)
    set --= Set(2,3)   // 删除一个集合
    println(set)
    set ++= Set(6,7,8) // 拼接两个集合
    println(set)
    println(set & Set(3,6))//求2个Set集合的交集
    set.remove(8)
    println(set)

List

  • List是scala中最重要的、也是最常用的数据结构
  • 有序、可重复
  • 不可变列表:
	val/var 变量名 = List(元素1, 元素2, 元素3...)
	//使用 Nil 创建一个不可变的空列表
	val/var 变量名 = Nil
	//使用 :: 方法创建一个不可变列表
	val/var 变量名 = 元素1 :: 元素2 :: Nil
  • 可变列表

必须导入 :import scala.collection.mutable.ListBuffer

	val list4 = ListBuffer[Int]()
    val list = ListBuffer(1,2,3,4) // 带初始元素
    println(list(0))    // 获取第一个元素
    println(list.head)  // 获取第一个元素
    println(list.tail)  // 获取除了第一个元素外其他元素组成的列表
    println(list += 5)  // 添加单个元素
    println(list ++= List(6,7)) // 添加一个不可变的列表
    println(list ++= ListBuffer(8,9)) //添加一个可变的列表(删除同样)
    println(list.isEmpty) // 列表是否为空
    list.toList   //根据可变的列表生成不可变列表,原列表不变
    list.toArray  //根据可变的列表生成不可变数组,原列表不变

小结

这里总结了scala的基本语法,由于主要用于函数式编程,需要形成特殊的语法习惯,熟能生巧!
更加详细的介绍可以查看教程,很多细节不必死记硬背,只需要大致总结即可,比如数组、映射、集合、列表都有可变和不可变之分等,随着使用的深入了解原理才是目的。
要抓主要矛盾,解决主要矛盾,作为大数据编程的利器,下一节会介绍到Spark/Flink的大量业务代码都会使用到的函数式编程
在这里插入图片描述

发布了3 篇原创文章 · 获赞 9 · 访问量 2798

猜你喜欢

转载自blog.csdn.net/weixin_39757637/article/details/104820586