2、Spark Core : Spark内核 ,最重要的一个部分。
3、Spark SQL : 类似于 hive 和 pig。数据分析引擎。sql语句提交到spark集群中运行。4、Spark Streaming :类似于 storm,用于流式计算、实时计算。本质:一个离线计算。------------------------------Scala编程语言---------------------------------------------
---------------Scala基础--------------------------
一、scala简介 1、scala是一个多范式的编程语言(支持多种方式的编程) (1)使用面向对象编程:封装、继承、多态 (2)使用函数式编程:最大的特定 (*)优点:代码非常简洁 (*)缺点:可读性太差,尤其是隐式类、隐式函数、隐式参数 2、安装和配置scala (*)基于JDK,先安装JDK (*)scala:2.11.8(spark 2.1.0) (*)配置环境变量:SCALA_HOME (*)%SCALA_HOME%\bin 配置到path中 下载地址:https://www.scala-lang.org 文档地址:https://www.scala-lang.org/api/2.11.8/#scala.math.package (*)开发环境 (1)REPL命令行 (2)IDEA : 需要安装scala插件。 二、Scala中的数据类型和变量常量 1、注意一点:scala中所有的数据,都是对象。 举例:1 java int 。在scala中,1 就是一个对象。 2、基本数据类型 Byte 8位有符号数字 Short 16位有符号数字 Int ... Long Float Double 字符串类型 String 字符 Char scala中字符串的插值操作:就是相当于字符串的拼接 scala> var s1 : String = "Hello " s1: String = "Hello "scala> "My name is Tom and ${s1}"
res1: String = My name is Tom and ${s1}插值操作时,需要加入 s
scala> s"My name is Tom and ${s1}" res2: String = "My name is Tom and Hello " 3、变量var和常量val scala> val s2 :String = "Hello all" s2: String = Hello allscala> s2 = "Hello everyone"
<console>:12: error: reassignment to val s2 = "Hello everyone" 4、Unit类型和Nothing类型 (1)Unit类型,就是java中的void,没有返回值 scala> val f = () f: Unit = () 返回值 Unit类型 () 代表了一个函数,这个函数没有返回值 (2)Nothing类型,在执行过程中,产生了异常Exception 举例: scala函数:scala中函数非常重要,是scala的头等公民 用法很多:函数式编程、高阶函数 def myFunction = 函数的实现 scala> def myFun = throw new Exception("Some Error") myFun: Nothing三、函数:头等公民
(一)scala内置函数,可以直接使用的函数
scala> max(1,2) <console>:12: error: not found: value max max(1,2) ^scala> import scala.math
final package mathscala> import scala.math._
import scala.math.__ 就相当于java中的 * 代表包内所有东西
scala> max(1,2) res4: Int = 2 res4: Int = 2 定义了一个变量 res4 ,接收了 max 函数的返回值。scala中支持类型的推导。 res4 = "" (二) 自定义函数 语法: def 函数名称([参数名称:参数类型]*) : 返回值类型 = { 函数的实现 } 举例: 1、求和 scala> def sum(x:Int,y:Int):Int = x + y sum: (x: Int, y: Int)Intscala> sum(1,2)
res5: Int = 3 2、求阶乘,5!= 5 * 4* 3 *2* 1 递归 scala> def myFactor(x:Int):Int = { | if(x<=1) | 1 | else | x*myFactor(x-1) | } myFactor: (x: Int)Intscala> myFactor(5)
res6: Int = 120 注意:没有return语句。 函数的最后一句话,就是函数的返回值。 3、求输入的年份是否是闰年 闰年: 普通闰年:可以被4整除但是不能被100整除的年份 世纪闰年:可以被400整除的年份 scala> def isLeapYear(x:Int) = { | if(( x%4 == 0 && x%100 != 0) || (x%400==0)) true | else false | } isLeapYear: (x: Int)Booleanscala> isLeapYear(2019)
res7: Boolean = falsescala> isLeapYear(2008)
res8: Boolean = true 1、( x%4 == 0 && x%100 != 0) || (x%400==0) 2、函数定义的时候,可以不写返回值,因为scala支持类型推导 四、循环语句 1、类似于java的用法 while dowhile for 2、foreach循环(Spark算子) 讲义在代码中 五、scala的函数参数1、函数参数的求值策略
(1)call by value : 对函数的实参求值,并且只求一次 (2)call by name : => 函数实参在函数体内部用到的时候,才会被求值 举例: scala> def test1(x:Int,y:Int) = x + x test1: (x: Int, y: Int)Intscala> test1(3+4,8)
res9: Int = 14scala> def test2(x : => Int,y : => Int) = x+x
test2: (x: => Int, y: => Int)Intscala> test2(3+4,8)
res10: Int = 14 执行过程对比: test1 ---> test1(3+4,8) ---> test1(7,8) ---> 7+7 ---> 14 test2 ---> test2(3+4,8) ---> (3+4) + (3+4) ---> 14 (3)复杂的例子 def bar(x:Int,y : => Int) : Int = 1 x 是 value y 是 name 定义一个死循环: def loop() : Int = loop 调用bar函数的时候: 1、bar(1,loop) 2、bar(loop,1) 哪个方式会产生死循环? scala> def bar(x:Int,y : => Int) : Int = 1 bar: (x: Int, y: => Int)Intscala> def loop() : Int = loop
loop: ()Intscala> bar(1,loop)
res11: Int = 1scala> bar(loop,1)
解析: 1、虽然 y 是 name, 每次调用的时候会被求值。但是,函数体内,没有调用到y. 2、x 是 value,对函数参数求值,并且只求一次。虽然后面没有用到x,但求值时产生了死循环。2、scala中函数参数的类型
(1)默认参数 当你没有给参数值赋值的时候,就会使用默认值。 def fun1(name:String="Tom") :String = "Hello " + name scala> def fun1(name:String="Tom") :String = "Hello " + name fun1: (name: String)Stringscala> fun1("Andy")
res0: String = Hello Andyscala> fun1()
res1: String = Hello Tom (2)代名参数 当有多个默认参数的时候,通过代名参数可以确定给哪个函数参数赋值。 def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age scala> def fun2(str:String = "Hello " , name:String = " Tom " ,age:Int = 20) = str + name + " age is " +age fun2: (str: String, name: String, age: Int)Stringscala> fun2()
res2: String = Hello Tom age is 20scala> fun2("Andy")
res3: String = Andy Tom age is 20scala> fun2(name="Andy")
res4: String = Hello Andy age is 20(3)可变参数 类似于java中的可变参数,即 参数数量不固定。 scala> def sum(args:Int*)= { | var result = 0 | for(s<-args) result +=s | result | } sum: (args: Int*)Int
scala> sum(1,2,3,4)
res5: Int = 10scala> sum(1,2,3,4,3,4)
res6: Int = 17 六、懒值(lazy)铺垫:Spark的核心是 RDD(数据集合),操作数据集合的数据,使用算子来操作RDD(函数、方法)
算子: Transformation : 延时加载,不会触发计算 Action : 会立刻触发计算。 定义:常量如果是lazy的,他的初始化会被延迟,推迟到第一次使用该常量的时候。 举例: scala> var x : Int = 10 x: Int = 10scala> val y : Int = x+1
y: Int = 11 y 的值是x+1 定义后会立即进行计算scala> lazy val z : Int = x+1
z: Int = <lazy>z的初始化会被延迟
scala> z
res0: Int = 11当我们第一次使用z的时候,才会触发计算
读文件: scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString words: String = 1 Tom 12 2 Mary 13 3 Lily 15scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString
words: String = <lazy>scala> words
res1: String = 1 Tom 12 2 Mary 13 3 Lily 15scala> lazy val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString
words: String = <lazy> 定义成lazy后,初始化被延迟,所以不会抛异常scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student123123121.txt").mkString
java.io.FileNotFoundException: H:\tmp_files\student123123121.txt (系统找不到指定的文件。) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at scala.io.Source$.fromFile(Source.scala:91) at scala.io.Source$.fromFile(Source.scala:76) at scala.io.Source$.fromFile(Source.scala:54) ... 32 elided七、例外:Exception
类似于java
还是有一些变化 文件操作: scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student.txt").mkString words: String = 1 Tom 12 2 Mary 13 3 Lily 15scala> val words = scala.io.Source.fromFile("H:\\tmp_files\\student1231312312312.txt").mkString
java.io.FileNotFoundException: H:\tmp_files\student1231312312312.txt (系统找不到指定的文件。) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at scala.io.Source$.fromFile(Source.scala:91) at scala.io.Source$.fromFile(Source.scala:76) at scala.io.Source$.fromFile(Source.scala:54) ... 32 elided 见代码 八、数组 1、数组的类型 (1)定长数组:Array scala> val a = new Array[Int](10) -----> (10) 就是数组的长度 a: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)scala> val a = new Array[String](10)
a: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)初始化赋给默认值
scala> val c : Array[String] = Array("Tom","Lily") c: Array[String] = Array(Tom, Lily)scala> val c : Array[String] = Array("Tom","Lily",1)
<console>:11: error: type mismatch; found : Int(1) required: String val c : Array[String] = Array("Tom","Lily",1) 不能往数组中添加不同类型的元素 (2)变长数组:ArrayBuffer scala> val d = ArrayBuffer[Int]() <console>:11: error: not found: value ArrayBuffer val d = ArrayBuffer[Int]() ^scala> import scala.collection.mutable._
import scala.collection.mutable._scala> val d = ArrayBuffer[Int]()
d: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer() scala> d += 1 res2: d.type = ArrayBuffer(1)scala> d += 2
res3: d.type = ArrayBuffer(1, 2)scala> d += (1,2,3,4)
res4: d.type = ArrayBuffer(1, 2, 1, 2, 3, 4)scala> d.
++ combinations groupBy mapResult reverse to ++: companion grouped max reverseIterator toArray ++= compose hasDefiniteSize maxBy reverseMap toBuffer ++=: contains hashCode min runWith toIndexedSeq +: containsSlice head minBy sameElements toIterable += copyToArray headOption mkString scan toIterator +=: copyToBuffer indexOf nonEmpty scanLeft toList - corresponds indexOfSlice orElse scanRight toMap -- count indexWhere padTo segmentLength toSeq --= diff indices par seq toSet -= distinct init partition size toStream /: drop inits patch sizeHint toString :+ dropRight insert permutations sizeHintBounded toTraversable :\ dropWhile insertAll prefixLength slice toVector << endsWith intersect prepend sliding transform WithFilter equals isDefinedAt prependAll sortBy transpose addString exists isEmpty product sortWith trimEnd aggregate filter isTraversableAgain readOnly sorted trimStart andThen filterNot iterator reduce span union append find last reduceLeft splitAt unzip appendAll flatMap lastIndexOf reduceLeftOption startsWith unzip3 apply flatten lastIndexOfSlice reduceOption stringPrefix update applyOrElse fold lastIndexWhere reduceRight sum updated canEqual foldLeft lastOption reduceRightOption tail view clear foldRight length reduceToSize tails withFilter clone forall lengthCompare remove take zip collect foreach lift repr takeRight zipAll collectFirst genericBuilder map result takeWhile zipWithIndex 举例:去掉数组中,最后两个元素 scala> d res5: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2, 3, 4)scala> d.trimEnd(2)
scala> d
res7: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 1, 2) 遍历数组: for循环、foreach: scala> var a = Array("Tom","Lily","Andy") a: Array[String] = Array(Tom, Lily, Andy)scala> for(s <- a ) println(s)
Tom Lily Andyscala> a.foreach(println)
Tom Lily Andy 数组的常见操作举例: scala> val myarray = Array(1,2,7,8,10,3,6) myarray: Array[Int] = Array(1, 2, 7, 8, 10, 3, 6)scala> myarray.max
res10: Int = 10scala> myarray.min
res11: Int = 1scala> myarray.sortWith(_>_)
res12: Array[Int] = Array(10, 8, 7, 6, 3, 2, 1)scala> myarray.sortWith(_<_)
res13: Array[Int] = Array(1, 2, 3, 6, 7, 8, 10) 解释:(_>_) 完整 : sortWith函数里面,参数也是一个函数 --> 高阶函数 _>_ 函数 def comp(a:Int,b:Int) = {if(a>b) true else false} (a,b) => {if(a>b) true else false} (a,b) => {if(a>b) true else false} ----> _>_ _>_ 是一个函数,传入两个参数,返回值是bool2、多维数组
和java类似,通过数组的数组来实现 scala> var matrix = Array.ofDim[Int](3,4) matrix: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0)) Array(0, 0, 0, 0) Array(0, 0, 0, 0) Array(0, 0, 0, 0) 三行四列的数组 scala> matrix(1)(2)=10scala> matrix
res15: Array[Array[Int]] = Array(Array(0, 0, 0, 0), Array(0, 0, 10, 0), Array(0, 0, 0, 0)) 数组下标是从0开始的 例子: 定义一个二维数组,其中每个元素是一个一维数组,并且长度不固定 scala> var triangle = new Array[Array[Int]](10) triangle: Array[Array[Int]] = Array(null, null, null, null, null, null, null, null, null, null) 初始化: scala> for(i <- 0 until triangle.length){ | triangle(i) = new Array[Int](i+1) | }scala> triangle
res17: Array[Array[Int]] = Array(Array(0), Array(0, 0), Array(0, 0, 0), Array(0, 0, 0, 0), Array(0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0), Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) 二维数组,如果使用 Array[Array[Int]](10) 声明时: 1、首先指定的是外层数据的长度 2、初始化内层数组的时候,再指定内层数组的长度九、映射 <key,value> Map
举例: 创建一个map,来保存学生的成绩 scala> val scores = Map("Tom" -> 80,"Andy"->70,"Mike"->90) scores: scala.collection.mutable.Map[String,Int] = Map(Mike -> 90, Tom -> 80, Andy -> 70) 1、Map[String,Int] key String value Int 2、scala.collection.mutable scala中,映射是有两种,一种是可变map,一种是不可变map scala.collection.mutable ---> 可变 scala.collection.immutable ---> 不可变 scala> val scores2 = scala.collection.immutable.Map("Tom" -> 80,"Andy"->70,"Mike"->90) scores2: scala.collection.immutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70, Mike -> 90) 映射的初始化: scala> val scores2 = scala.collection.mutable.Map(("Tom",80),("Andy",70)) scores2: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70) scala> scores2=1 <console>:15: error: reassignment to val scores2=1 映射的操作: 1、获取映射中的值 scala> val chinese = scala.collection.mutable.Map(("Tom",80),("Andy",70)) chinese: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)scala> chinese("Tom")
res18: Int = 80scala> chinese.get("Andy")
res19: Option[Int] = Some(70) scala> chinese("aaaa") java.util.NoSuchElementException: key not found: aaaa at scala.collection.MapLike$class.default(MapLike.scala:228) at scala.collection.AbstractMap.default(Map.scala:59) at scala.collection.mutable.HashMap.apply(HashMap.scala:65) ... 32 elidedscala> chinese.get("Andy1231312")
res21: Option[Int] = None chinese("aaaa") get("Andy1231312") 需求:判断key是否存在,若不存在,返回默认值 scala> if(chinese.contains("aaa")){ | chinese("aaa") | }else{ | -1 | } res22: Int = -1 scala> chinese.getOrElse("aaaa",-1) res23: Int = -12、更新映射中的值 注意:必须是可变映射 scala> chinese res24: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 70)
scala> chinese("Andy")=20
scala> chinese
res26: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20) 3、映射的迭代 for foreach scala> chinese res27: scala.collection.mutable.Map[String,Int] = Map(Tom -> 80, Andy -> 20)scala> for(s<-chinese) println(s)
(Tom,80) (Andy,20)scala> chinese.foreach(println)
(Tom,80) (Andy,20) foreach 高阶函数 十、元组 : Tuple scala 中的tuple : 是不同类型值的集合 scala> val t1 = Tuple("Tom","Lily",1) <console>:14: error: not found: value Tuple val t1 = Tuple("Tom","Lily",1) ^scala> val t1 = Tuple3("Tom","Lily",1)
t1: (String, String, Int) = (Tom,Lily,1) Tuple3 代表 Tuple中有三个元素scala> val t1 = Tuple2("Lily",1)
t1: (String, Int) = (Lily,1)scala> val t2 = (1,2,4,"Hello")
t2: (Int, Int, Int, String) = (1,2,4,Hello) tuple操作: 访问tuple中的元素 scala> val t1 = Tuple3("Tom","Lily",1) t1: (String, String, Int) = (Tom,Lily,1)scala> t1.
_1 _3 copy hashCode productArity productIterator toString zipped _2 canEqual equals invert productElement productPrefix xscala> t1._1
res30: String = Tomscala> t1._3
res31: Int = 1如何遍历Tuple中的元素 注意:Tuple并没有提供一个foreach函数,我们使用productIterator 遍历分为两步: 1、使用 productIterator 生成一个迭代器 2、遍历 scala> t1.productIterator. != copyToBuffer forall min reduceRightOption toIterable ## corresponds foreach minBy sameElements toIterator + count formatted mkString scanLeft toList ++ drop getClass ne scanRight toMap -> dropWhile grouped next seq toSeq /: duplicate hasDefiniteSize nonEmpty size toSet :\ ensuring hasNext notify slice toStream == eq hashCode notifyAll sliding toString GroupedIterator equals indexOf padTo span toTraversable addString exists indexWhere partition sum toVector aggregate filter isEmpty patch synchronized wait asInstanceOf filterNot isInstanceOf product take withFilter buffered find isTraversableAgain reduce takeWhile zip collect flatMap length reduceLeft to zipAll collectFirst fold map reduceLeftOption toArray zipWithIndex contains foldLeft max reduceOption toBuffer → copyToArray foldRight maxBy reduceRight toIndexedSeq scala> t1.productIterator.foreach(println) Tom Lily 1 十一、scala中的文件操作 类似于java的io 举例: 1、读取文件 2、读取二进制文件 3、从url中获取信息 4、写入文件 5、scala中调用java的类库 见代码
---------------Scala面向对象--------------------------
scala是一个多范式的编程语言(支持多种方式的编程)
类似于java 有区别一、面向对象的概念
1、封装 : 把属性和操作属性的方法,写在了一起。class 2、继承 3、多态 java中面向对象的概念,也是用与scala二、定义类:class
举例:创建一个学生类
三、内部类(嵌套类):在一个类的内部,定义了另外一个类见代码
四、类的构造器:两种
1、主构造器 : 和类的声明在一起,并且一个类只能有一个主构造器 class Course(var courseName:String,var grade : Int) 2、辅助构造器 : 一个类可以有多个辅助构造器,通过this来实现 五、object对象:相当于java中的static1、Object 对象中的内容都是静态的
2、如果和类名相同,则成为伴生对象 3、scala中没有static关键字 4、举例 (1)使用object来实现单例模式:一个类里面只有一个对象 在java中,把类的构造器定义成private的,并且提供一个getInstance,返回对象 在scala中,使用object实现 (2)使用App对象:应用程序对象。 好处:可以省略main方法。 六、apply方法 val t1 = Tuple3("Tom","Lily",1) 没有new关键字,但是也创建出来对象,用了apply方法 注意:apply方法必须写在伴生对象中。 七、继承 1、extends 和java一样 object HelloWorld extends App 2、抽象类:代码中 抽象字段: package day0323/**
* Created by root on 2019/3/23. * * 抽象字段 抽象属性 * * 定义: 没有初始值的字段 */abstract class Person1{
//定义抽象字段 val id :Int val name : String }如果不加abstract 报错
abstract class Employee1 extends Person1{}
下面两种方式均不会报错class Employee2() extends Person1{
val id :Int = 1 val name : String = "" } class Employee2(val id:Int,val name:String) extends Person1{ }object Demo3 {
}
精彩评论