spark新一代的内存级大数据云计算框架,是大数据的重要的内容 spark使用scala编写的 scala是scalable Language的简写,是一门多范式(范式/编程方式【面向对象/函数式编程】)的编程语言 Martin odersky于年开始设计Scala Spark的兴起带动Scala语言的发展
1.首先安装jdk 2.在http://www.scala-lang.org/网站下载 3.最好在用户系统配置SCALA_HOME 4.安装在c盘里不要有空格,和中文 5.Scala如果在idea2018中要用需要安装一个插件
1.直接在终端执行Scala,但是只能一行一行的执行 2.:load 加文件名来编译 3.还可以通过编译打包的方式运行scalac 文件名 scala -classpath . 文件名 或者java -classpath .:/usr/local/scala/lib/scala-library.jar 文件名 注意第三种方式必须加类定义,而且必须退出scala编译环境
1.这里的文件名不一定必须和Object定义的文件名一样 2.每个独立的应用程序都必须有一个定义在单例对象中的main方法 3.区分大小写,这里可以采用;,也可以省略
Byte,Short,Int,Long,Char,Float,Double,String,Boolean
:quit
需要导入包
只需要在字符串字面量前加一个“s”和“f”,s是不支持格式化,f是支持格式化 读写文件 1.写入文件,注:必须关闭写入流,不关闭流就写不进去数字
3.读出文件,调用getLines方法用迭代器的方法输出内容,记住关闭流
控制结构 if表达式 与java不同的是scala的if语句会返回一个值,这与java中的三元运算类似
For循环表达式 (1)提供了各种容器遍历的强大功能,而且该处的变量不需要关键字val或者var修饰 变量<-表达式被称为生成器,而且for循环可以对任何类型的容器进行枚举
(2)还可以添加过滤条件,对for循环语句过滤
(3)还可以添加多个if语句用分号隔开
(4)可以用多个生成器
(5)yield关键字可以作为返回for循环语句的返回值当做一个容器返回结果,也叫for推导式,意思是生成一个数组返回
注:中间加分号 1.异常处理结构 scala不支持检查型异常,所有的异常都是非检查型的,因此在方法声明中不需要加throw子句,当然也支持throw关键字手动抛出
(5)对循环语句的控制 在scala中不提供continue,而是通过一个名称为Breaks的类实现类似的功能,该类位于scala.util.control包下,Breaks类中有两个方法用于对循环结构的控制,即breakable,break,通常都是配对使用的 import util.control.Breaks breakable{ if()break }
在scala中经常需要用到数据结构,比如数组(Array),元组(Tuple),列表(list),映射(Map),集合(Set)
数组是一种可变的,可索引的,元素具有相同类型的数据集合 Scala提供了一种参数化类型的通用数组Array[T],T是任意的数组类型 1.Scala会自动选择最近的数组参数作为Array的参数类型 2.第二种方式没有选择new关键字,是因为使用了Scala伴生对象apply方法,但是需要**注意:**的是尽管两个变量都是用val定义的但是仅仅表明这两个变量不能在指向其他对象但是对象本身是可以变的,因此可以对数组的内容进行改变 3,.也提供了ofDim来定义二维和三维数组
元组是对多个不同类型对象的封装。Scala提供了TupleN类(N的范围是1~22),用于创建一个包含N个元素的元组 因此可以使用下划线“_”来访问加上从1开始的索引值来访问元组的元素 例如:Tuple_1是返回的是Tuble 还可以一次行提取出元组中的元素并且赋值给变量
Scala中提供了一套丰富的容器(Collection)库,定义了列表(List),映射(Map),集合(Set)等常用的数据结构。 根据组织方式和操作方式,可以分为有序和无序,可变和不可变等不同的容器类别。Scala用了三个包来组织容器的类,分别是**scala.collection:**封装了一些可变和不可变得容器的特质(java中的接口)或者是超类,包中的容器通常都具备对应的可变和不可变得实现 scala.collection.mutable元素可变的容器 scala.collection.immutable是元素不可变的容器 下图为scala.collection包中的容器的宏观层级关系 所有的容器的根为Traverable特质,表示可遍历的他为所有的容器定义了抽象的foreach方法,该方法用于对容器的元素进行遍历和操作,混入Traverable特质必须给中foreach的具体方法的实现,Iterable特质,表示元素可以一个一个的迭代,而Iterable继承下的三个特质分别是序列(Seq)、映射(Map)和集合(Set),这种最大的区别就是元素的索引方式 序列:从0开始的整数进行的索引 映射:按照键值进行索引 集合:没有索引
1.序列容器的根是collection.Seq特质。其具有两个子特质 LinearSeq和IndexedSeq。LinearSeq序列具有高效的 head 和 tail 操作,而IndexedSeq序列具有高效的随机存储操作 2.实现了特质LinearSeq的常用序列有列表(List)和队列(Queue)。实现了特质IndexedSeq的常用序列有可变数组(ArrayBuffer)和向量(Vector) 序列----列表 列表: 一种共享相同类型的不可变的对象序列。定义在scala.collection.immutable包中 不同于Java的java.util.List,scala的List一旦被定义,其值就不能改变,因此声明List时必须初始化
列表有头部和尾部的概念,可以分别使用head和tail方法来获取 head返回的是列表第一个元素的值 tail返回的是除第一个元素外的其它值构成的新列表,这体现出列表具有递归的链表结构 strList.head将返回字符串”BigData”,strList.tail返回List (“Hadoop”,“Spark”) 构造列表常用的方法是通过在已有列表前端增加元素,使用的操作符为::,例如: 执行该语句后strList保持不变,而otherList将成为一个新的列表: List(“Apache”,“BigData”,“Hadoop”,“Spark”) Scala还定义了一个空列表对象Nil,借助Nil,可以将多个元素用操作符::串起来初始化一个列表 注意:除了head、tail操作是常数时间O(1),其它按索引访问的操作都需要从头开始遍历,因此是线性时间复杂度O(N)。
序列(Sequence)——向量(Vector)
Vector可以实现所有访问操作都是常数时间 序列(Sequence)——Range Range类:一种特殊的、带索引的不可变数字等差序列。其包含的值为从给定起点按一定步长增长(减小)到指定终点的所有数值 Range可以支持创建不同数据类型的数值序列,包括Int、Long、Float、Double、Char、BigInt和BigDecimal等 (1)创建一个从1到5的数值序列,包含区间终点5,步长为1 2)创建一个从1到5的数值序列,不包含区间终点5,步长为1 (3)创建一个从1到10的数值序列,包含区间终点10,步长为2 4)创建一个Float类型的数值序列,从0.5f到5.9f,步长为0.3f
集合(set):不重复元素的容器(collection) 列表(List)中的元素是按照插入的先后顺序来组织的,但是,“集合”中的元素并不会记录元素的插入顺序,而是以“哈希”方法对元素的值进行组织,所以,它允许你快速地找到某个元素
集合包括可变集和不可变集,分别位于scala.collection.mutable包和scala.collection.immutable包,缺省情况下创建的是不可变集 如果要声明一个可变集,则需要提前引入scala.collection.mutable.Set
映射(Map):一系列键值对的容器。键是唯一的,但值不一定是唯一的。可以根据键来对值进行快速的检索
Scala 的映射包含了可变的和不可变的两种版本,分别定义在包scala.collection.mutable 和scala.collection.immutable 里。默认情况下,Scala中使用不可变的映射。如果想使用可变映射,必须明确地导入scala.collection.mutable.Map 对于这种访问方式,如果给定的键不存在,则会抛出异常,为此,访问前可以先调用contains方法确定键是否存在 可变的映射 university2 + = (“TJU”->“Tianjin University”) //添加一个新元素 university2 + = (“SDU”->“Shandong University”,“WHU”->“Wuhan University”) //同时添加两个新元素
迭代器(Iterator)不是一个容器,而是提供了按顺序访问容器元素的数据结构 迭代器包含两个基本操作:next和hasNext。next可以返回迭代器的下一个元素,hasNext用于检测是否还有下一个元素 除next和hasnext方法外,在对一个迭代器调用了某个方法后,不要再次使用该迭代器
1.class Counter{ //这里定义类的字段和方法 } 2.字段定义:用val或var关键字进行定义 3.方法定义: def 方法名(参数列表):返回结果类型={方法体} class Counter { var value = 0 def increment(step:Int):Unit = { value += step} def current():Int = {value} } 使用new关键字创建一个类的实例 val myCounter = new Counter myCounter.value = 5 //访问字段 myCounter. increment(3) //调用方法 println(myCounter.current) //调用无参数方法时,可以省略方法名后的括号
Scala类中所有成员的默认可见性为公有,任何作用域内都能直接访问公有成员
除了默认的公有可见性,Scala也提供private和protected,其中,private成员只对本类型和嵌套类型可见;protected成员对本类型和其继承类型都可见 为了避免直接暴露public字段,建议将字段设置为private,对于private字段,Scala采用类似Java中的getter和setter方法,定义了两个成对的方法value和value_=进行读取和修改 scala> :load /usr/local/scala/mycode/Counter.scala Loading /usr/local/scala/mycode/Counter.scala… defined class Counter scala> val myCounter = new Counter myCounter: Counter = Counter@f591271 scala> myCounter.value_=(3) //为privateValue设置新的值 scala> println(myCounter.value)//访问privateValue的当前值 3 Scala语法中有如下规范,当编译器看到以value和value_=这种成对形式出现的方法时,它允许用户去掉下划线_,而采用类似赋值表达式的形式 myCounter.value= 3 // 等效于myCounter.value_=(3)
def 方法名(参数列表):返回结果类型={方法体} 方法参数前不能加上val或var,所有的方法参数都是不可变类型 无参数的方法定义时可以省略括号,这时调用时也不能带有括号;如果定义时带有括号,则调用时可以带括号,也可以不带括号 方法名后面的圆括号()可以用大括号{}来代替 如果方法只有一个参数,可以省略点号(.)而采用中缀操作符调用方法 如果方法体只有一条语句,可以省略方法体两边的大括号
// An highlighted block scala> :load /usr/local/scala/mycode/Counter1.scala Loading /usr/local/scala/mycode/Counter1.scala… defined class Counter scala> val c=new Counter c: Counter = Counter@30ab4b0e scala> c increment 5 //中缀调用法 scala> c.getValue() //getValue定义中有括号,可以带括号调用 res0: Int = 0 scala> c.getValue // getValue定义中有括号,也可不带括号调用 res1: Int = 0 scala> c.current() // current定义中没有括号,不可带括号调用 <console>:13: error: Int does not take parameters c.current() ^ scala> c.current // current定义中没有括号,只能不带括号调用 res3: Int = 0当方法的返回结果类型可以从最后的表达式推断出时,可以省略结果类型 如果方法返回类型为Unit,可以同时省略返回结果类型和等号,但不能省略大括号 class Counter { var value = 0 def increment(step:Int) { value += step }//赋值表达式的值为Unit类型 def current()= value //根据value的类型自动推断出返回类型为Int型 }
Scala类的定义主体就是类的构造器,称为主构造器。在类名之后用圆括号列出主构造器的参数列表
主构造器的参数前可以使用val或var关键字,Scala内部将自动为这些参数创建私有字段,并提供对应的访问方法
// An highlighted block scala> class Counter(var name:String) //定义一个带字符串参数的简单类 defined class Counter scala> var mycounter = new Counter("Runner") mycounter: Counter = Counter@17fcc4f7 scala> println(mycounter.name) //调用读方法 Runner scala> mycounter.name_=("Timer") //调用写方法 scala> mycounter.name = "Timer"// 更直观地调用写方法,和上句等效 mycounter.name: String = Timer如果不希望将构造器参数成为类的字段,只需要省略关键字var或者val
Scala类可以包含零个或多个辅助构造器(auxiliary constructor)。辅助构造器使用this进行定义,this的返回类型为Unit 每个辅助构造器的第一个表达式必须是调用一个此前已经定义的辅助构造器或主构造器,调用的形式为“this(参数列表)”
// An highlighted block //代码文件为/usr/local/scala/mycode/Counter2.scala class Counter { private var value = 0 private var name = "" private var step = 1 //计算器的默认递进步长 println("the main constructor") def this(name: String){ //第一个辅助构造器 this() //调用主构造器 this.name = name printf("the first auxiliary constructor,name:%s\n",name) } def this (name: String,step: Int){ //第二个辅助构造器 this(name) //调用前一个辅助构造器 this.step = step printf("the second auxiliary constructor,name:%s,step:%d\n",name,step) } def increment(step: Int): Unit = { value += step} def current(): Int = {value} } // An highlighted block scala> :load /usr/local/scala/mycode/Counter2.scala Loading /usr/local/scala/mycode/Counter2.scala… defined class Counter scala> val c1=new Counter the main constructor c1: Counter = Counter@319c6b2 scala> val c2=new Counter("the 2nd Counter") the main constructor the first auxiliary constructor,name:the 2nd Counter c2: Counter = Counter@4ed6c602 scala> val c3=new Counter("the 3rd Counter",2) the main constructor the first auxiliary constructor,name:the 3rd Counter the second auxiliary constructor,name:the 3rd Counter,step:2 c3: Counter = Counter@64fab83b定义函数最通用的方法是作为某个类或者对象的成员,这种函数被称为方法,其定义的基本语法为 def 方法名(参数列表):结果类型={方法体} 字面量包括整数字面量、浮点数字面量、布尔型字面量、字符字面量、字符串字面量、符号字面量、函数字面量和元组字面量
函数字面量可以体现函数式编程的核心理念在函数式编程中,函数是“头等公民”,可以像任何其他数据类型一样被传递和操作,也就是说,函数的使用方式和其他数据类型的使用方式完全一致了这时,我们就可以像定义变量那样去定义一个函数,由此导致的结果是,函数也会和其他变量一样,开始有“值”就像变量的“类型”和“值”是分开的两个概念一样,函数式编程中,函数的“类型”和“值”也成为两个分开的概念,函数的“值”,就是“函数字面量”Hadoop和Spark可以相互协作,由hadoop的HDFS、HBase等组件负责存储数据,由Spark负责数据的计算,为了能让spark操作HDFS的数据必须先启动HDFS 操作命令如下 cd /usr/local/hadoop ./sbin/start-dfs.sh 可以通过jps判断是否成功 结束后可以使用./sbin/stop-dfs.sh关闭命令 spark-shell:REPL(交互式解释器):默认进入Scala交互式解释器 如果想要进入python,需要执行pyspark命令 交互式解释器:执行完一行就会立即输出结果,不必等到整个程序执行完。