【Scala】基础概念

一、概论

Scala源自Java
  • Scala构建在JVM之上
  • Scala与Java兼容、互通
Scala的优势
  • 多范式编程:面向对象编程、函数式编程
  • 表达能力强,代码精简
  • 最重要的特性:类型推断
大数据与Scala
  • Spark采用Scala语言设计
  • 提供的API更加优雅
  • 基于JVM的语言更融入Hadoop生态圈

二、Scala 安装 – Window

1. 下载安装包解压
https://downloads.lightbend.com/scala/2.11.8/scala-2.11.8.msi
2. 设置环境变量
SCALA_HOME D:\Kaifa\scala-2.11.8 PATH %SCALA_HOME%\bin CLASSPATH %SCALA_HOME%\bin;%SCALA_HOME%\lib\dt.jar;%SCALA_HOME%\lib\tools.jar
3. 测试
WIN+R cmd scala -version

三、Scala 安装 – Linux

1. 下载安装包
wget https://downloads.lightbend.com/scala/2.11.8/scala-2.11.8.tgz
2. 解压
tar -zxf scala-2.11.8.tgz mv scala-2.11.8 /usr/local/scala
3. 设置环境变量
vi /etc/profile export SCALA_HOME=/usr/local/scala export PATH=$PATH:$SCALA_HOME/bin . /etc/profile
4. 测试
scala -version :quit

四、Scala 安装 – IDEA插件

1. 添加插件并重启IDEA
File – Setting – Plugin Scala install
2. 创建无特征Mvn项目,导入Mvn依赖
<properties> <scala.version>2.11.8</scala.version> </properties> <dependencies> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>2.11.8</version> </dependency> </dependencies>
3. 首次创建Scala文件
new file -> Hello.scala create scala
4. 创建入口,编程名言
object Hello { def main(args: Array[String]): Unit = { print(“hello world”) } }
5. =)
hello world

五、Scala 概述

面向对象特性
  • 每个值都是对象
  • 对象的数据类型和行为由类(Class)和特征(Trait,类似于interface)描述
  • 利用特质实现混入式多重继承
函数式编程
  • 每个函数都是一个值
  • 支持高阶函数、柯里化(currying)、样例类(case class)及模式匹配……
Scala是静态类型语言
扩展性:隐式类、字符串插值

六、Scala 变量与常量

变量 Var(variable)
赋值后可以改变,生命周期中可以被多次赋值
var 变量名称:类型=xxx var name = “jason” name:string = jason var name:String = “jason” //直接调用java的String
常量 Val(value)
赋值后不可变,类似于Java中的final变量
尽量使用val,val没有线程安全问题,效率较高
val 常量名称:类型=xxx val money = 100 money:int = 100
使用类型别名定义变量
type关键字
type 类型别名=类型 type T = String //defined type alias T val name:T = “jason” name:T = jason

七、Scala 关键字列表

39 个关键字
11 个符号

八、Scala 数据类型

Scala与Java有着相同的原始数据类型
数据类型
描述
Byte
8位有符号整数。数值区间-128 ~ 127
Short
16位有符号整数。数值区间-32768 ~ 32767
Int
32位有符号整数。数值区间 -2147483648 ~ 2147483647
Long
64位有符号整数。 -9223372036854775808 ~ 9223372036854775807
Float
32位IEEE 754 单精度浮点数
Double
64位IEEE 754 双精度浮点数
Char
16位无符号Unicode字符。区间值为U+0000 ~ U+FFFF
Boolean
true或false
String
等于java.lang.String

九、Scala 数据类型层次结构

Any
所有类型的超类(顶级类型)
AnyVal
表示值类型的超类
AnyRef
表示引用类型的超类,对应java.lang.Object
Unit
表示无值,类似Java中的void
Nothing
所有类型的子类
Null
表示null或空引用
YourClass
自定义类
String
隶属于AnyRef
ScalaObject
隶属于AnyRef

十、字符串插值

s 插值器
  • 允许将变量引用、表达式直接插入字面字符中
val name=”James” println(s”Hello,$name”) //Hello,James print(s”1+1=${1+1}”) //1+1=2 println(s”hello+${6*4}”) //hello+24
f 插值器
  • 指定格式化输出
val height=1.9d val name=”zhangsan” println(f”$name%s is $height%2.2f”) //zhangsan is 1.90
raw 插值器
  • 忽略换行符、制表符等符号,直接输出原始值
s”a\nb” //将输出换行符 raw”a\nb” //输出原始字符

十一、Scala 条件控制

if 语句
val x=10 if(x>0){ print(“x大于0”) }
if…else 语句
val x=10 if(x>10){ print(“x大于10”) }else{ print(“x小于等于10”) } //:paste val x=10 if(x>10){ print(“x大于10”) }else if(x==10){ print(“x等于10”) }else{ print(“x小于10”) }
Case
o match{ case 1 => println(“yes”) case _ => println(“no”) } var s = “hello” throwableToLeft { s.toUpperCase } match { case Right(s) => println(s) case Left(e) => e.printStackTrace }

十二、条件语句返回值

Scala任何表达式都有返回值
val x=10 val y=if(x==10) x+1 else x //单行表达式可以省略{} //y=?
代码块“{…}”也是表达式,返回值为最后一个表达式结果
val x=10 val y={ println(“我是代码块”) x+1 } //我是代码块 //y: Int = 11 val x=10 val y={ x+1;print(“我是代码块”) } //一行内有多个表达式,需要使用“;”分隔 //我是代码块y: Int = 11

十三、Scala 循环控制-1

while循环
  • Scala中可以不用在语句结束位置显示地使用分号(;)
var num: Int = 0; while ( num < 100 ) { println( num );num = num + 1; } var num: Int = 0; do { println( num );num = num + 5; } while ( num < 200 }
for循环
val num:Int = 10; for ( i <- 1 to num ) { println( i * 100 ); } //until:后开区间,不取后值 for { i: Int <- 1 until 100 } { val y = 2*i; println( y ); }
模拟continue和break
//1. 利用return达到break的效果 def main(args: Array[String]): Unit = { var a = random.nextInt(90)+10 test(a) def test(x:Int): Unit ={ for(i <- 1 to x){ println(i) if(i==10){ return } } } } //2. 使用breakable方法停止循环 import scala.util.control.Breaks._ def main(args: Array[String]): Unit = { test() def test(): Unit = { println(“Start”) val l = List(1,2,3,4,5,6,7,8,9,10) breakable{ for(x <- l){ println(2*x) if(x > 6)break } } println(“Done”) } } //3. 使用循环条件达到continue效果 for (i <- 1 to 10; if i % 2 == 0) { val y = 2 * i println(y) }
十四、Scala 循环控制-2
中断
  • by 2:表示步长为2
import scala.util.control.Breaks._ val num:Int = 10; for ( i: Int <- 1 to num by 2 ) { if(i>=5) break; println( i * 100 ); }
for循环过滤
  • 多个条件时使用分号(;)
for(i<-1 to num by 2;if i%3==0;if i<=5){println(i)} val num:Int = 10; for ( i: Int <- 1 to num; if i%2==0;if i>5 ) { println( i * 100 ); }

十五、Scala 循环控制-3

for循环返回值
  • for 循环中的 yield 会把当前的元素记下来,保存在集合中,循环结束后将返回该集合。也称for推导式
val num:Int = 10; //for循环使用yield将具有返回值 var retVal=for ( i: Int <- 1 to num; if i%2==0;if i>5 ) yield i; //增强for遍历数组 for(a<-retVal){ println(a); } //输出6 8 10

十六、练习:使用for循环

需求说明
使用Scala编程输出如图所示加法表
var x=0 var y=6 var z=6 for(i<- 0 to z){println(s”$x+$y=$z”);x=x+1;y=y-1}
//九九乘法表 var i=1 var j=1 for(i<- 1 to 9;j<- 1 to i){print(s”$j*$i=${i*j}\t”);if(i==j)println()}

十七、Scala 数组

存储固定大小的元素
数组索引从0开始
//数组创建方式一 var a1:Array[String] = new Array[String](3) //泛型使用方括号 a1(0)=”Jason” //数组元素访问使用圆括号 a1(1)=”Marie” a1(2)=”Jimmy” //数组创建方式二 var a2=Array(“Jason”,”Marie”,”Jimmy”) //调用Array的伴生对象中的apply()返回Array实例 //数据创建方式三:区间数组 var a3=Array.range(1,10,2) //1-10,步长为2

十八、Scala 元组

可以包含不同类型的元素
最多支持22个元素 (Tuple1~Tuple22)
使用下划线“_”访问元素,“_1″表示第一个元素
//元组声明方式一 var tp1 = (“Mike”, “123 ABC street”, 58) println(tp1._1) println(tp1._2) println(tp1._3) //迭代元组 tp1.productIterator.foreach{ i =>println(“Value = ” + i )} //元组声明方式二 var tp2 = new Tuple3(“Mike”, “123 ABC street”, 58) //元组声明方式三 def mike = “Mike” -> 5 tp1.productIterator.foreach{ i =>println(“Value = ” + i )} //嵌套元祖 def tp3 = “hydra”->6->7 Value=(hydra,6) Value=7 //输出scala.Tuple2 tp3.getClass Class[_ <: ((String, Int), Int)] = class scala.Tuple2 //将元组元素依次赋给三个变量 val(name, address, age) = tp1 println(name) println(address) println(age)

十九、Scala 集合-1

Seq
  • 序列,元素按顺序排列
Set
  • 集合,元素不重复
Map
  • 映射,键值对集合

二十、Scala 集合-2

不可变集合
  • scala.collection.immutable,默认Scala选择不可变集合
可变集合:
可以修改、添加或移除一个集合的元素
  • scala.collection.mutable
var list2=scala.collection.mutable.ListBuffer(1,2,3) list2(1)=4 list2 //scala.collection.mutable.ListBuffer[Int] = ListBuffer(1, 4, 3)

二十一、Scala 集合-3

scala.collection.immutable
Set:ListSet、HashSet、TreeSet
Map:ListMap、HashMap、TreeMap
Seq:Vector、String、Range、List、Stack、Stream、Queue
IndexedSeq:索引序列,通过索引得到高效的随机读取
LinearSeq:线性序列,高效的写入,开头和尾部方便查找

二十二、Scala 集合-4

scala.collection.mutable
常用类:
Buffer – ListBuffer
Map – TreeMap / HashMap
Set – HashSet

二十三、Scala 集合-5

常用集合
名称
可变/不可变
示例
Buffer
mutable
val buffer = scala.collection.mutable.ArrayBuffer[Int](10, 20, 30);
buffer+=(2,3)
Array
mutable
val arr=Array(1,2,3)
List
immutable
val lst=List(1,2,3)
Map
mutable
val stu= Map(“name” -> “Jason”, “age” -> “18”)
Set
mutable/immutable
val set=Set(1,2,3)
Vector
immutable
val v=Vector(1, 3, 5, 7, 11, 13)
Stack
mutable/immutable
val st=scala.collection.mutable.Stack(1,2,3) //堆栈,先进后出
Queue
mutable/immutable
val q=scala.collection.mutable.Queue(1,2,3) //队列,先进先出
BitSet
mutable/immutable
val bit=scala.collection.mutable.BitSet(3,2,0) //位集合
ListMap
immutable
val map = scala.collection.immutable.ListMap(1->”one”, 2->”two”)
HashSet
mutable
val set= scala.collection.mutable.HashSet(1,2,3)
HashMap
mutable
val stu= scala.collection.mutable.HashMap(“name” -> “Jason”, “age” -> “18”)
Jar包位置

二十四、Scala List 常用操作

var c = List[Char](‘a’, ‘b’, ‘c’) var x = ‘x’ +: c // (x, a, b, c) var y = c :+ ‘x’ // (a, b, c, x) import scala.collection.mutable._ var lb = ListBuffer[Int](1, 2, 3, 4) lb += (21, 33) // 88 +=: lb //88, 1, 2, 3, 4, 100, 21, 33 List(77, 66) ++=: lb lb += 100 //1, 2, 3, 4, 100
var l = List[Int](2, 3, 4, 6, 8, 9, 11, 20) var x = l grouped 3 //等价l.grouped(3) x.next() //(2, 3, 4) x.next() //(6, 8, 9) var y = l sliding 2 y.next() // (2, 3) y.next() // (3, 4)
var a1 = Array[Int](1, 2, 3, 4) var a2 = Array[Int](100, 200, 300, 400) var a = List.concat(a1, a2) //Array->List a3=a1++a2 //Arrays->Array a(3) = 333 //Error a3(3)=333 //OK var b = Array(333, “333”, ‘3’, false ) var c = List.concat(a, b) val x = a.filter( _ %2 != 0 ) val y = a.reverse var m = a.groupBy(t => t%2 == 0) var n = a.slice(2, 4) a.sorted //1, 2, 3, 4, 100, 200, 300, 400 a.sorted( Ordering.Int.reverse ) a.sortWith( _ > _ ) a.sortBy( x => x ) //升序 a.sortBy( x => x*(-1) ) //降序
练习
var c = List(‘a’,’b’,’c’) //创建List类型集合 ‘x’+:c //添加元素(不可变) c=’x’+:c //开头添加元素(可变,重新赋值) var b=’z’+:c //添加元素并赋值给其他集合 c=c:+’d’ //队尾添加元素 import scala.collection.mutable._ //为ListBuffer导入可变集合包 val 1b = ListBuffer(1,2,3,4) //创建ListBuffer集合 lb+=100 //队尾添加元素 lb+=(22,33) //队尾添加多个元素 90+=:lb //开头添加元素 List(55,66)++=:lb //开头添加一个List集合 var lb2=List(1,2,3,4,5,6,7,8) //创建一个List集合 var iter=lb2 grouped 3 //为集合分3组,生成迭代器 iter.next() //输出迭代器下一组的值 var iter2=lb2.sliding(2) //为集合生成另一个迭代器,滑动长度默认为1 var iter3=lb2.sliding(2,2) //为集合生成另一个迭代器,长度为2,滑动为2 var a=Array(1,2,3,4) //创建集合a var b=Array(5,6,7,8) //创建集合b var c=List.concat(a,b) //合并2个Array,并转集合类型为List var aa=a++b //合并2个Array成另一个Array aa(3)=111 //修改aa第4个元素的值 var b=Array(333,”333″,’3′,false) //创建一个多元素类型的Array var c=List.concat(a,b) //合并2个多元素集合为List lb2.filter(x=>x%2!=0) //过滤器,过滤掉2的倍数 lb2.filter(_!=5) //过滤掉5,(下划线等于x=>x) var a = Array(10,1,2,3,4,5,6,7,8) //创建一个int集合 a.reverse //倒序排列 a.sorted //正序排列 a.sorted(Ordering.Int.reverse) //传入新参数后,倒序排列 a.sortWith(_>_) //简版降序 a.sortWith(_<_) //简版升序 a.sortBy(x=>x) //升序 a.sortBy(x=>x*(-1)) //降序 var m = a.groupBy(t=>t%2==0) //以偶数分组 //Map(false -> Array(1, 3, 5, 7), true -> Array(10, 2, 4, 6, 8)) var n=a.slice(0,7) //切割集合,从下标0到元素值7

二十五、Scala Set 常用操作

var s = Set(“ab”, “yz”) s += “mn” //mn, ab, yz s += “mn” //?? s -= “yz” //mn, ab var t = Set(“ab”, “gh”, “mn”, “st”, “yz” ) t — s //gh, st, yz t ++ s //ab, gh, mn, st, ya\ var s = Set(“ab”, “yz”) var t = Set(“ab”, “gh”, “mn”, “st”, “yz” )
可变Set
import scala.collection.mutable._ val s1=scala.collection.mutable.Set(“ab”,”yz”) s1 += “mn //TreeSet var os = SortedSet(1,99,66,54,77) os +=33
练习
var s = Set(1,2,4) //创建一个Set集合,不可变 s+1 //不可添加重复元素 s+5 //队尾添加元素(不可变) s=s+5 //队尾添加元素(可变,重新赋值) var s2=(1,2,4,5,6) //创建第二个集合 s & s2 //交集 s intersect s2 //交集(并排序) s|s2 //并集 s union s2 //并集 s++s2 //并集 s2 &~ s //差集(大放前) s2 diff s //差集(大放前) s2–s //差集(大放前)

二十六、Scala Map 常用操作

var m = Map[String, Int](“a”->1, “b”->2, “c”->3, “d”->4, “e”->5, “f”->6, “g”->7, “h”->8, “i”->9) m(“a”) //通过key寻找value m.keys //获取所有key m.values //获取所有value m.getOrElse(“z”,0) //如果有z,返回value,没有就返回0 m += (“j”->11) //给集合增加一对键值 m += (“j”->12) //同样的key,会覆盖前一个值 for((k,v)<-m){println(k+”:”+v)} //遍历map集合 //创建一个自动key排序的map val m2 = scala.collection.SortedMap(“dd”->25,”cc”->30,”aa”->28,”bb”->29) //创建一个可变的map val m3 = scala.collection.mutable.Map(“dd”->25,”cc”->30,”aa”->28,”bb”->29) var n = m ++ Map[String, Int](“a”->3, “j”->99) //重新赋值,并生成新的集合 n -= (“g”, “e”) //去除一对键值

二十七、Scala Stream & Vector

Stream是List惰性版
它只确定第一个值,后面的值用到的时候,再求值,可以防止数据过大,全部加载导致OOM
val stream = (1 to 1000).toStream stream //查看集合,默认只显示第一个 stream.head //查看第1个值 stream.tail //从1个值开始,输出,默认到下一个 stream(3) //查看第4个值 stream.tail //从1个值开始,输出到上一步求的值
Vector(索引序列)拥有连续的内存空间,利于随机存取(直接访问)
val v = Vector.empty :+ 2 :+ 2 val v1 = v ++ Vector[Int](3) //在v的基础上,队尾增加一个3 v.length //集合长度(int类型) v1.length //集合长度(int类型) val x = IndexedSeq(1,2,3)

二十八、练习2:列表分组排序

需求说明
  • 请将下列同学分为2组,依次每3人一组,组内按名排序
  • “Jason,Vince,Dwan,Lynn,Stephon”
var a=List(“Dwan”,”Jason”,”Vince”) var b=List(“Lynn”,”Stephon”) var c=List.concat(a,b) c=c.sorted

二十九、Null 等其他数据和类型

Null
一个数据类型,继承自AnyRef(集合)
null
表示一个空值
Nothing
Nothing是所有类型的子类型,没有Nothing的实例,啥也不是
Nil
定义集合空的初始值,继承自List[Nothing]
None
继承自Option[Nothing]
Option
可能有值[Some(T)],可能没有值[None]
Try
Success或者Failure,要么成功要么失败
Left & Right
Either的子类。当返回值可能有2种类型的时候,做判断,要么a,要么b
Null & null
def a(thing:Null):Unit={ println(“ok”) } val b:Null=null val c:String=null a(b) //通过,b即Null类型 a(c) //报错,c是null空值,但还属于String类型 a(null) //通过,null自身是Null类型
Nothing
val emptyIntList:List[Int]=List[Nothing]() //nothing可以是Int类型 val emptyStringList:List[String]=List[Nothing]() //nothing可以是String类型 val emptyStringList:List[String]=List[Nothing](“abc”) //String不是nothing //任何空的集合必定是空的
Option
val s:Option[String] = None s == Node //true s.getOrElse(“wu”) //String = wu val o:Option[Int] = scala.util.Try(“123i”.toInt).toOption o == None //Boolean = true val o:Option[Int] = scala.util.Try(“123”.toInt).toOption o.get //Int = 123 def getAStringMaybe(num:Int):Option[String]={ if(num>=0) Some(“A positive number!”) else None //A number less than 0? Impossible! } getAStringMaybe:{num:Int}Option[String] getAStringMaybe(-1) //Option[String] = None getAStringMaybe(2) //Option[String] = Some(A positive number!)
Left & Right
def divideBy(x:Int,y:Int):Either[String,Int]=if(y==0) Left(“Dude,can’t divide by 0”) else Right(x/y) divideBy(100,2) match{ case Left(a) => println(a) case Right(b) => print(“right=%d”.format(b)) } //right=50
Try
import scala.util.Success import scala.util.Failure import scala.util.Try Try(“124”.toInt) match{ case Success(a) => println(“the value is %d”.format(a)) case Failure(e) => println(“Exception occurred – %s”.format(e.getMessage)) } //Yes Try(“hi”.toInt) match{ case Success(a) => println(“the value is %d”.format(a)) case Failure(e) => println(“Exception occurred – %s”.format(e.getMessage)) } //No

三十、Scala 字符串格式化

“%1$s-%2$s-%3$s”.format(“spark”,”scala”,”ml”) “%08.3f”.format(11.56789) “%d%%”.format(86)
数据类型到字符串的转换
转换符
说明
示例
%s
字符串类型
“wwx”
%c
字符类型
‘w’
%b
布尔类型
true
%d
整数类型(十进制)
99
%x
整数类型(十六进制)
FF
%o
整数类型(八进制)
77
%f
浮点类型
99.99
%a
十六进制浮点类型
FF.35AE
%e
指数类型
9.668e+5
%g
通用浮点类型(f和e类型中较短的)
%h
散列码
%%
百分比类型
%n
换行符
%tx
日期与时间类型(x代表不同的日期与时间转换符
搭配转换符的标志
标志
说明
示例
结果
+
为正数或者负数添加符号
(“%+d”,112)
+112
左对齐
(“%-5d”,112)
|112   |
0
数字前面补0
(“%05d”, 99)
00099
空格
在整数之前添加指定数量的空格
(“% 5d”, 99)
|   99|
,
以“,”对数字分组
(“%,f”, 9999.99)
9,999.990000
(
使用括号包含负数
(“%(f”, -99.99)
(99.990000)
#
如果是浮点数则包含小数点,如果是16进制或8进制则添加0x或0
(“%#x”, 99)
(“%#o”, 99)
0x63
0143
<
格式化前一个转换符所描述的参数
(“%f和%<3.2f”, 99.45)
99.450000和99.45
$
被格式化的参数索引
(“%1d,s”, 89,”abc”)
89,abc

发表回复