Scala简介
------------------------------
1.scala是面向对象的、面向函数的基于静态类型的编程语言。
2.安装Scala,版本选型2.11.8。原因:spark版本选型为2.1.2(最好是x.x.2版本),由scala2.11.8版本编译的
注意:a.安装目录不能有“ ”(空格)出现,否则抛:主类找不到.....
b.必须安装JDK,需版本为1.8.X以上;
3.安装IDEA。安装Scala插件
a.选择【File】-->【Setting】-->【plugins】--> 选择scala,点击Install JetBrains Plugins..
b.选择【File】-->【New-->project】 -->选择scala选项,并指定【IDEA】,next
c.添加 工程名,指定JDK版本,指定Scala版本,然后Finish;
Scala基本语法
----------------------------------------
1.Scala有两种变量,val和var。
val类似于Java里的final变量。一旦初始化了,val就不能再赋值了
在Scala中 字符串类型就是:java.lang.String(Int,Float,Boolean,都是Scala.Int等)
2.函数定义
函数定义采用def,格式如下:
def 函数名(参数列表[arg*:type]...):返回值类型 = {函数体,表达式}
注意:每个函数参数后面必须带前缀冒号的类型标注,因为Scala编译器没办法推断函数参数类型;但是可以进行结果类型的推断;
scala>def max(x:Int,y:Int):Int={if(x>y)x else y}
scala>def max(x:Int,y:Int)={if(x>y)x else y}
scala>def max(x:Int,y:Int)=if(x>y) x else y
scala>def max(x:Int,y:Int)={println(x);println(y);if(x>y)x else y}
无返回值,采用Unit
3.遍历or枚举
scala> val _list = List(1,2,3,4,5,6)
_list: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> _list.foreach(x=>println(x))或scala> _list.foreach(println(_))或scala> _list.foreach(println)
1
2
3
4
5
6
scala> for(list <- _list) println(list)
4.List集合的相关操作
表达式“1 :: twoThree”中,::是它右操作数(列表twoThree)的方法,等同于twoThree.::(1)
5.说明:
Array和List都不可变,它为何这样设计呢?它最大的好处就是用在高并发的地方。因为在高并发时,如果多个线程都访问一个公用的变量,那这个变量就要加共享锁。
这里也是最容易出错的地方,不光影响性能的问题。那scala呢,干脆就换了个思路,来解决多线程时并发的问题。它换了什么思路呢?它就是让这个共享变量不可变。
那这个集合只能读,不能写,就自然不会存在并发访问问题。所以这两个类要比java中的性能高。
当然scala也提供了可变版本,ArrayBuffer对应Array,ListBuffer对应List。
6.补充:Array和List的区别
Array是连续存储结构,所以初始化时必须设定初始值,List是不连续的存储结构,所以可以不初始化。当不确定数组大小时,使用List替代Array;
当需要大量查找操作时使用Array替代List;当需要进行频繁的插入和删除时使用List代替Array。List相对比Array占用更多空间。
查询某个值而言hashtable更快。当然它们结构完全不同,没有可比性。毕竟数组是节约空间,而hash表是散列的,牺牲空间来换取速度。
------------------------------------------------------------------------------------------------------------------------
List
List(类似java中的LinkedList)基于链表实现,插入元素比较快,随机访问速度稍慢。
val list = List[Int]() //构造一个空元素的集合,元素类型为Int
val list = List(1,2,3,4); //构造一个集合,初始化其内容,可以根据初始化的类型判断其类型,所以无需写泛型。
list.head //list中的第一个元素
list(3) //按下标访问,获取第4个元素,但越往后越慢。
list.length //获取链表的长度
注意:和java不同的是,它的内容不可变。 list(3)=40这是不行的,它是只读的。
换成var list也不行,它们概念完全不同。看看它的内存分配。
List(1,2,3,4,5)它在堆内存中,除了基本变量和局部变量都是在堆内存中。如main方法中的局部变量使用的是栈内存。val也好,var也好这个变量的引用都在它都在栈内存。
变量在堆内存中,只是说这个变量的引用指向堆内存。
var只是说这个引用的地址可以改变,val是引用的地址不能发生变更。
既然是不可变的集合,那需要增加一个元素怎么做呢?
list.:+(6) //list :+ 6,它会创建一个新的list,最后一个元素是6。这点和java中String的处理如出一辙。
注意实现方式,计算现有集合然后转换成一个新的集合,这个思想是scala乃至spark都广泛使用,如spark中的RDD也是这个思想。
那在list前面加元素呢?
val list3 = 6 +: list //+号在前就是在前面加,在后面就是在后面加,冒号跟着list走
合并两个list为一个list
val lista = List(1,2)
val listb = List(5,6)
println(lista ::: listb) //使用三个冒号连接
如果listb = List(1,2)呢? //list是可以有重复元素
中间插入元素
println(list.take(2) ::: List(0) ::: list.takeRight(2))
take(2)取list集合的前2个,takeRight(2)取list集合的后两个元素
删除左侧元素
println(list.drop(2)) //删除左边的2个元素
删除右侧元素
println(list.dropRight(2)) //删除右边的2个元素
更新元素
println(list.updated(2,30)) //更新第三个元素为30。其实它是创建了一个新的数组,而不是真正更新了。
------------------------------------------------------------------------------------------------------------------------
ArrayBuffer可变数组
//ArrayBuffer需要导入包,mutable可变,immutable不可变
import scala.collection.mutable.ArrayBuffer
val buffer = ArrayBuffer(1,2,3,4,5)
buffer += 6
println(buffer)
结果:ArrayBuffer(1,2,3,4,5,6)
它就非常类似java中的String和StringBuffer。String是不可变的,StringBuffer是可变的。
注意:java下导入包是java.*,而scala导入时scala.collection_
------------------------------------------------------------------------------------------------------------------------
Set
元素不能重复,重复的会自动剔除,乱序
val set = Set(1,2,3,4,45,3,2,6)
println(set)
结果:Set(45, 1, 2, 6, 3, 4)
------------------------------------------------------------------------------------------------------------------------
Map
val map = Map(1 -> "北京", 2 -> "上海") //->前面是key,后面是值
val map2 = map + (3 -> "广州") //产生新的map
val map3 = map -2 //删除key=2的元素
println(map)
println(map2)
结果:
Map(1 -> "北京", 2 -> "上海")
Map(1 -> "北京", 2 -> "上海", 3 –> "广州")
------------------------------------------------------------------------------------------------------------------------
Tuple元组
代表键值对,一般的键值对是一个键一个值,tuple一个键可以有多个值。
val t1 = (1,"北京","100086")
println(t1._1) //访问key,注意tuple下标是从1开始
println(t1._2) //获取北京
println(t1._3) //获取邮编
tuple可以设置多个值,不是无限的,最多22个
两个值它的类型就是Tuple2,三个值它的类型就是Tuple3,最多到Tuple22。