biji

1.强类型语言 弱类型语言
强类型语言:定义对象或变量时,需要指定其归属类型

          一旦一个变量类型确定,它所归属的类型不可再变

弱类型语言:定义变量时不用指定变量类型

          在程序运行中,可以改变变量的的归属类型

scala变量定义:
var str = "abcd"
java: String str = "abcd"
这样写法不是没有指定str的类型,而是没有显式的指定str的类型,它隐式的从变量值中自动判断
显式写法:
var str:String = "abcd"

2.声明变量有两种修饰符
var: 变量可被重新赋值
val: (常量)不可被重新赋值
在编程过程中,能使用val的地方不要使用var
3.基础数据类型
java基础数据类型,它对应的变量,不是对象,不能通过"."运算符来访问对象的方法
scala对应java的基础数据类型的类型,对应的变量,是对象,可以通过“.”调用对象的属性或方法
4.String类型的字面量
val s1 = "abcd"
val s2 = "ab"cd"
val s3 = """ab".eo24/.*cd"""

字符串模板嵌套
println(s"name:$name,age:$age")
println(s"name:$name,age:${age}aa")
println(s"""name:$name

 | age:$age
 | over
 | """
 | )

5.基础数据类型之间的转换方法

对象.to类型
123.toDouble
"123".toInt
445.33.toString
6.scala中的运算符
scala中运算符不是语法,而是函数(对象)
a+b 等同于 a.+(b)
前者是后者的简写
当一个对象通过点调用其方法的时候,如果该方法只有1个参数,那么点号可以省略 小括号可以省略,对象、方法、参数之间用空格隔开即可
如果方法有多个参数,那么点号可以省略,但是小括号不能省略

==运算符(Java)
String a = new String("abc")
String b = a
a == b

==在scala中方法,这个方法等同于equal方法
val a = new String("abc")
val b = new String("abc")

a == b a.equal(b)

scala中没有基础数据类型的++ --运算符
7.标识符 符合java的规范
类标识符,驼峰式命名首字母大写
变量 方法标识符,驼峰式命名,首字母小写
包标识符,全小写,层级使用点分割

val在scala中虽然定义的是常量,但是,一般都用变量的规则来命名标识符
8.scala注释规则和java一致
9.语句块
java中的语句块全部都是过程,没有返回值,只有方法语句块中用return才能有返回值
scala中大部分的语句块都是有返回值的,而且不需要return
java中语句块的作用主要用来划分作用域
scala中的语句块除了划分作用域之外还可以带返回值

val str1 = "111"
val str2 = {

 val str3 = s"${str1}defg"
 str3

}
println(str3) --访问不到
scala中语句块的最后一句,就是该语句块的返回值

8.if...else...
scala中的if else语法是有返回值的,因此可以在变量的赋值上就使用if else语法
另外scala中没有三目运算表达式
9.while循环
语句块中是没有返回值的

10.for循环
for也是scala中少数没有返回值的语句块之一
但是scala中也提供了一种方式(yield)让其具有返回值的能力
java for
for(int i=0;i<10;i++){}
scala 的for 更像 foreach
for(String i:slist){}
for(i <- list){}

通过守卫来限定判断条件
for(i <- 1 to times if i%2==0) println(s"2print:$i")

scala里面没有break 也没有continue
1.但是可以使用scala中提供的特殊类型Breaks来实现break
2.通过return 终止整个函数的方式也可以终结循环

11.Unit类型
java里无返回值的方法类型是void
scala中没有void,它使用Unit类型来代替
Unit的实例就是“()”

12 函数定义
函数定义和对象的定义一样,编译器可以通过返回值来自动判断返回值
因此,绝大多数的函数定义,都不写返回值类型
只有一种情况例外:递归函数
def functionName(x:Int,y:Int):Int = {

 x+y

}
在scala因为函数是对象,因此它的定义方式有很多

下面的这个函数定义是一个过程函数的定义,过程函数是没有返回值的,即返回值是Unit

只要函数这么定义它的返回值就是Unit,就算在函数体内return也不会返回结果

def functionName(x:Int,y:Int){

 x+y

}
如果定义函数时把函数的类型指定为Unit那么不管该函数的语句块最后一句结果是什么,
该函数的返回值始终是Unit()
13 函数类型
因为scala中函数是一等公民,因此它和对象一样也有自己的类型
因为函数中涉及的类型包括参数的类型,返回值类型,因此函数的类型就用参数类型和返回值类型来共同定义
如:
def plusInt(x:Int,y:Int)={

  x+y

}
那么该函数有两个参数都是Int,有一个返回值也是Int,那么在scala中的函数类型描述是:
(Int,Int)=>Int
其中 => 符号分割参数定义(输入)类型 和 返回值(输出)的类型
(Int)=>Int

Int =>Int
(Int,Int)=>Int

14 函数字面量(匿名函数)
函数的字面量也是用=>来进行定义,它左边是参数(输入),右边是返回值(输出)
val plusIntVal:(Int,Int)=>Int = (x,y)=>x+y
val plusIntVal1 = (x:Int,y:Int)=>x+y

15 def定义的函数不可以被当做对象来被传递
val定义的函数可以被当做函数来被传递
val定义的函数名称,后面不加小括号代表的是对函数对象的引用,后面添加小括号代表的是对函数的调用

16 Array是可变(元素可变)的,它和java的数组T[]是对应的
数组是定长的,定义的时候必须指定长度,一旦声明长度不可发生变化

17 ArrayBuffer是变长数组,该类型对象在声明定义时可以不用指定长度,随着程序的运行
可以随意增间该对象的元素

18 List是不可变的元素列表,里面的元素不可更改,长度也不可更改
List具有递归结构(Recursive Structure)和其它类型集合一样,它具有协变性
比方说Student 是 Person的子类
List[Studnt] 也是 List[Person]的子类

19 val def lazy定义变量的区别

20 scala的类定义也是使用class关键词后面跟类的名称然后大括号
class Person {}
Java类体内:

          属性
               静态属性
               非静态属性
          方法 静态方法
               非静态方法
          
          静态代码块 :类被加载时执行

scala类体内:

           属性:非静态属性
           方法:非静态方法
           非静态代码块 :每一次被实例化的时候都会被执行一次
                          (class里面的过程代码(代码块),其实就是类的构造方法)

scala中没有static关键词
scala中用Object(单例类)来承担静态的成员定义

在Class定义的属性和方法必须要通过实例化的对象才能调用
在Object里面定义的属性和方法,直接用Object名称就可以调用

scala的成员也可以使用
private 和protected修饰但是没有public

----跟java一致的部分
没有(public):所有其他代码都可以访问
private:只有自己可以访问
protected:只有子类和同包下面的可以访问
----跟java一致的部分
private:只有自己可以访问

        除了自己可以访问之外可以额外开放访问权限

protected:只有子类和同包下面的可以访问

        除了子类和同包外也可以额外开放访问权限

21 构造方法
Java构造方法:有默认无参构造方法

             自定义构造方法时默认构造方法消失
             构造方法可以重载 [public 类名(参数列表){}]
             不同的构造方法之间地位是平等的

Scala构造方法:有无参的默认构造方法

              构造方法也可以重载
              不同构造方法之间地位不平等,每个scala类都只有一个唯一的主构造方法
              除了主构造方法之外,所有次构造方法体内都必须直接或间接的调用主构造方法来完成对象的构建
              主构造方法的声明是类声明后面来写
              次构造方法是写在类体内的,它的名字统一都叫this
              所有的次构造方法在方法体内必须先间接或直接的调用主构造方法后才能写自己的构造逻辑代码,构造方法不需要返回值,它返回值是Unit

              构造方法可以使用默认值参数
              class ConstructorWithDefault(var attr1:String,var attr2:String = "defaultATTR2",var attr3:Int = 3)
              这样能大大提高构造方法调用的灵活性
              可以通过在主构造方法参数前面加private的方式来讲主构造方法私有化
              class ConstructorMainPrivate private(var attr1:String,var attr2:String)

22 单例对象object
单例对象的属性和方法,可以直接通过单例对象的名称来调用,不需要实例化,它本身就是一个对象
23 如果定义一个object和一个class 他们的名称一样如Student,那么在编译成class文件的时候
他们的会共用一个Student.class的文件
这样一个object和class他们互为伴生
在伴生类中可以通过类名调用伴生对象的属性和方法
但是伴生对象不可以调用伴生类的属性和方法

伴生类和伴生对象之间可以相互访问private的成员
但是如果private添加泛型限定则会有额外的限制,如private[this]

24 apply方法在scala中是有特殊作用的方法,它可以直接通过object名称后面加小括号的形式来调用
object Student 在其中定义一个apply方法

Student.apply() ====(等用于) Student()
apply方法和普通方法一样可以被重载

25 抽象类
java抽象类: 不能够被实例化

           可以定义属性,可以定义已实现的方法,也可以定义抽象方法
           子类必须实现抽象类中所有的抽象方法

scala抽象类:不能够被实例化

            可以定义属性,可以定义已实现的方法
            可以定义未被初始化的属性,和未被实现的方法
            子类必须初始化所有抽象类中未初始化的属性
                必须实现抽象类中未被实现的方法
            在定义未实现的方法上必须指定返回值类型

            抽象类可以定义构造方法,构造方法上也可以通过var val等修饰符声明属性
            抽象类主构造方法上有属性定义,子类在继承时必须给抽象类的构造方法传值
            
            在子类被实例化的时候会先调用父类的构造方法再调用子类的构造方法

26 继承
scala中的继承和java一样使用extends修饰符来定义父类和子类之间的关系
子类会从父类中继承访问控制权限内的属性和方法
子类重写父类方法的时候,如果父类是抽象类,重写的方法是抽象方法override关键词可以省略
否则必须写override

27 匿名类
当我们想要实例化一个类型的对象的时候,如果这个类型是一个抽象类,或者是一个接口
而我们又不想重新定义一个类型来继承抽象类或实现接口
这时候我们可以使用匿名类
可以使用
new AbstractType(){

 //实现或重写父类的方法

}
28 组合和继承
当我们想定义一个类型,并且希望这个类型具有比较强大的功能的时候
我们可以考虑两种方式:1 继承 操作简单

                             在功能使用上面,直接调用可访问的属性和方法(不需要实例化父类的对象)
                             
                             继承只能单继承
                             继承侵入性太强,没办法解耦
                     2 聚合  操作复杂 会额外写很多代码,比方说接口的定义
                             对功能方法的调用需要通过实例对象来进行
                             
                             可以多方引入,没有单继承出现的问题
                             方便解耦,使用接口来引入想要扩展的类型

29 scala的总父类型是Any
AnyVal相当于java的基础数据类型
AnyRef相当于java中的Object
30 java的接口:interface

                     常量
                     未实现的方法

scala的接口:traits

                     常量
                     未实现的方法
                     
                     变量 初始化的变量和未初始化的变量
                     已实现的方法

两种语言在定义接口实现类的时候都必须实现全部接口未实现的方法(scala中包含未初始化的变量)

traits可以多实现 而抽象类只能继承一个

trait不可以被实例化

如果一个类要实现多个接口的话,第一个接口前用extends,后面每一个接口前都用with
class ImpClass extends Trait1 with Trait2 with Trait3...
如果一个类既要继承另一个类又要实现多个接口,那么被继承的类写在extends后面,所有的接口前面加with
class ExtendedAndImpClass extends SuperClass with Trait1 with Trait2 ...

trait之间也可以继承,可以被多继承

31 包和引入
scala中引入包(import)的基本用法和java一致,除了导入包下所有类型的时候Java用的是*,scala中用的是_
scala中可以在引入统一个包的时候用一行代码引入多个类型
import java.util.{Date,Random}

scala中可以在任意的地方引入包
在代码块里用import引入包它的作用域就是代码块内
如果在scala文件的最上方引入,那么它在整个文件内都生效

scala中引入的类型的时候可以给类型起别名
import scala.collection.mutable.{Queue=>MutableQueue}

scala还可以使用import的方式类隐藏类型
import scala.collection.immutable.{HashMap=>_,_}
相当于在当前引入的所有immutable下的类型隐藏HashMap
在使用HashMap的时候就不会发生类名冲突的问题

包的定义基本用法和java一致,同时也有更高级的用法
包的定义可以嵌套,可以和目录不一致

32 包对象
包对象上经常用来定义一个包下可以使用的常量,函数,object等
在使用这些函数和常量时可以无引用的调用,类似 println

一个包下面只能有一个包对象
定义方式:package object name...
包对象所定义的包下的类可以无引用的使用包对象中的属性和方法

包对象定义的包外的类也可以无引用的使用包对象中的属性和方法,但是需要使用import来导入
import com.zhiyou.bd17.oo.packagetest._

33 权限访问控制和包的关系
private或protected是scala中仅有的两个权限控制修饰

private后面可以通过添加中括号的方式来更灵活的进行自己的权限控制
中括号中可以写:
1.伴生对象伴生类可以各自访问私有成员
2.内部类
private[this] -- 限制上述伴生对象访问自己的私有成员
private[类名] --
private[包名] -- 扩充包下的类也可以访问自己的私有成员

34 创建maven的scala项目
1.找模板(scala maven archetype) http://docs.scala-lang.org/tutorials/scala-with-maven.html

G:net.alchim31.maven
A:scala-archetype-simple
V:1.5

2.intellj中new--》project--》maven

勾选create from archetype
点击 add archetype按钮
模板下载完之后选择我们添加的模板:net.alchim31.maven:scala-archetype-simple
next

3.填写自己项目的GAV
4.next---next---finish
5.import changens
6.pom中修改

 2.11
 2.11.8
改成自己的版本

删除:

  org.specs2
  specs2_${scala.tools.version}
  1.13
  test


  org.scalatest
  scalatest_${scala.tools.version}
  2.0.M6-SNAP8
  test


删除:

-make:transitive

删除 test.scala.samples下的所有代码

7.打开App程序 右键运行

打印结果 
scala maven就创建成功

在pom中导入mysql驱动
用scala写一个mysql的增删改查
(Int,String)=>Double

(x,y)=>{x+y}
(x:Int,y:String)=>{x+y}

val functionName:函数类型 = 函数字面量
val functionName = 函数字面量

35 函数书写省略规则

1.如果对对象调用函数,函数只接受一个参数的话 点号和小括号都可省略

                     如果函数接受多个参数的话,点号可以省略,小括号不可以省略

2.在传递函数作为参数的时候,因为函数位置处可以推断出函数的类型,因此被传递的函数字面量可以不用指定参数的类型
3.当字面量函数只有一个参数的时候,小括号也可以省略
4.当参数在函数体内只被使用一次的时候,参数的定义可以被省略,在函数体使用_来代替参数

 注意参数的使用顺序是和参数的顺一致的

5.如果传递一个函数,不写字面而是用val定义的函数名称的话,则不需要考虑参数的传递
6.调用函数的时候,如果函数的参数相对比较复杂,可以使用大括号来代替小括号

36 scala中函数的参数可以在定义是赋一个默认值,如果一个参数有默认值,那么在这个函数被调用时有默认值的参数可以不用传参,不传参就代表使用默认值
如果传参的话就使用传递的参数值
scala中在调用函数的时候可以不按照函数定义的参数顺序来传递,可以通过带名传参的方式来实现

37 高阶函数
把函数当做参数的函数
把函数当做返回值的函数(闭包)
38 函数的柯里化
把一个函数的多个参数用多个小括号隔开 这种函数定义的形式就叫函数的柯里化
def sum(x:Int,y:Int) = x+y

def sum(x:Int)(y:Int) = x+y

1.可以通过传部分参数让其返回一个函数
2.和隐式参数结合使用,因为隐式参数的定义范围是小括号

39 隐式转换
scala中定义了隐式转换的机制,让我们可以在写代码的时候很多转换或者参数的部分由编译器自动给我们添加,大大减少代码量
1.可以在方法或者变量前面添加隐式转换标记implicit
2.可以将方法的参数前面添加隐式转换标记implicit
3.可以在类前面添加隐式转换标记implicit

隐式值和隐式参数函数
implicit在修饰函数参数的时候它必须加载参数小括号的最前面,同时小括号内的所有参数都将被生命为隐式参数
implicit修饰参数后的函数如果是被柯里化并且拥有非隐式的参数的话,带有implicit的小括号应该写在不带隐式参数的小括号后面

带有隐式参数的函数被调用时,必须得先定义隐式值
隐式值在一个应用中只能定义一个,重复定义会报错
同一个类型的隐式值只能定义一个否则会编译报错:隐式值冲突

隐式值一般被定义在包对象中

隐式函数一般用于类型的自动转换(扩充某些类型的功能)

隐式类型一般也是用于类型转换的
隐式类型不能直接定义在类的最外层,它需要放在object里面来定义
隐式类型必须主构造函数中要接受参数,这个参数正式它转换的类型

40 def定义的函数 函数名称后面加不加小括号都是对函数的调用
val定义的函数 函数名后面不加小括号是对函数的引用,加小括号才是调用
41 scala中的模式匹配 match case

java switch case
只能够对基础数据类型进行匹配
每一个case都需要加break跳出匹配
只能够对值进行匹配
只是一种流程控制语法无返回值

match case
可以对任意类型进行匹配
不需要加break跳出,所有case表达式中,只要有一个被匹配会马上跳出
除了能对值进行匹配外还有近7、8中匹配方式
它有返回值

val map = Map(1->"abc",2->"def")
for((k,v) <- map){

 println(s"$k,$v")

}
map.foreach(

 case (k,v)=>println(s"$k,$v")

)

42 case class 是scala的特殊类型,它是专门用于承载数据的类型,类似java中的JavaBean类
在声明case class的时候主构造函数必须要显示声明,属性都写在主构造方法中

case class由 编译器自动给我们生成其伴生对象里面,并且在伴生对象里自动帮我们实现apply方法
case class主构造方法中的参数可以用var或val声明,自动会被当做类的属性,相当于有一个默认
val,如果想把属性声明成变量需要显示添加一个var
case class 自动帮我们重写美化的toString方法,还有hashCode 方法和 equal方法

spark shell用法

val file = sc.textFile("hdfs://centos1:9000/wctest.txt")
val result = file.flatMap(x=>x.split("\s")).map(x=>(x,1)).reduceByKey((x1,x2)=>x1+x2)
result.saveAsTextFile("/sparkwcresult")

43 数据处理应用场景
批处理 bi分析,olap
流处理 实时需求
交互式处理 开发调试,数据挖掘,模型计算,机器学习

44 数据处理方式
函数式数据处理,使用某种语言的api,通过方法的调用完成数据的处理
sql

result = ax+by+cz+c

45 spark程序的数据处理过程,是在driver上来进行解析编译,在具体对数据处理的时候需要一个触发点来触发执行计算过程
这个触发点就是rdd的action方法

rdd的处理方法(函数)有两种
transformation 转换 对数据进行计算转换抽取,只记录处理过程而不真正计算数据,例如,一行变多行,一个单词变kv对,把一个key下的所有value累加
action 行为 对数据进行读值,触发对数据的计算过程,触发后会把action前面的所有的transformation启动执行,一般不改变数据,只是对数据的结果值进行读取

46 intellj中的程序直接运行在spark的standalone模式下
1.创建artifact(项目编译打包)
2.修改conf的master设置:val conf = new SparkConf().setMaster("spark://centos1:7077").setAppName("word count")
3.在sc下添加我们intellj打的包,打包过程,build---》build artifacts---》build:

 sc.addJar("D:\\javaproj\\sparkbd17\\out\\artifacts\\sparkbd17_jar\\sparkbd17.jar")

45 spark程序的数据处理过程,是在driver上来进行解析编译,在具体对数据处理的时候需要一个触发点来触发执行计算过程
这个触发点就是rdd的action方法

rdd的处理方法(函数)有两种
transformation 转换 对数据进行计算转换抽取,只记录处理过程而不真正计算数据,例如,一行变多行,一个单词变kv对,把一个key下的所有value累加
action 行为 对数据进行读值,触发对数据的计算过程,触发后会把action前面的所有的transformation启动执行,一般不改变数据,只是对数据的结果值进行读取

46 intellj中的程序直接运行在spark的standalone模式下
1.创建artifact(项目编译打包)
2.修改conf的master设置:val conf = new SparkConf().setMaster("spark://centos1:7077").setAppName("word count")
3.在sc下添加我们intellj打的包,打包过程,build---》build artifacts---》build:

 sc.addJar("D:\\javaproj\\sparkbd17\\out\\artifacts\\sparkbd17_jar\\sparkbd17.jar")

47 SparkContext
spark功能使用的主入口点
它负责连接spark 集群,并且在spark集群上创建RDD
,创建accumulators,broadcast variables(共享变量)

实例化方法:new SparkContext(conf) 多例

           SparkContext.getOrCreate(conf)   单例

SparkConf
实例化: new SparkConf()
实力化时如果不指定是否加载默认,它会加载默认配置文件,如:core-site.xml,hive-site.xml,hbase-site.xml,如果不想引入这些文件,可以:new SparkConf(false)
可以链式调用配置其参数
conf.set("","").set("","")
new SparkConf().setMaster("local").setAppName("My app")

构建RDD

       从hadoop体系相关的文件中获取数据组装成rdd
       binaryFiles()
       binaryRecords()
       hadoopFile()
       hadoopRDD()
       newAPIHadoopFile()
       newAPIHadoopRDD()
       sequenceFile()
       textFile()
       wholeTextFiles()
       objectFile()
       从内存中获取数据,组装成rdd
       makeRDD()
       parallelize()


创建累加器:
       register(acc: AccumulatorV2[_, _], name: String)
       doubleAccumulator(name: String)
       collectionAccumulator[T]
       longAccumulator(name: String)
创建广播变量
       broadcast[T](value: T)(implicit arg0: ClassTag[T])

默认最小分区数:defaultMinPartitions
部署模式:deployMode

48 RDD
1.它有一组分区构成,不同的分区在不同的集群节点上
2.可以通过调用它的方法(transformation和action),来对rdd的每一个分区进行各自计算(对rdd进行分布式计算)
3.RDD之间是有依赖关系的,在spark中很少有rdd的独立的

4.对于kv对的rdd可以使用分区器Partitioner来对其进行分区
5.在对文件进行加载的时候,它会优先在拥有文件的节点上启动加载executor
49 RDD容错
rdd是通过依赖关系(DAG)来容错的

50 RDD api

转换型

      flatMap   ----- 一输入对多输出  输入是元素,输出是集合对象
      map        ----- 一个输入对应一个输出,如果没有返回,对应元素的返回值会是()
  mapPartitions ----- 一个输入分区对应一个输出分区,新老rdd之间的元素可以不用一对一
     keyBy     ----- 输入一个元素x输出一个kv,v就是原来的元素,k是由x经过算子计算而来,算子把x转成k

聚合型

     aggregate
     
     聚合计算函数:
     reduce 方便使用,只需要定义一个迭代算子,聚合结果的类型要和原rdd的泛型中的数据类型保持一致
     fold   比reduce多了一个初值的指定,其他的和reduce一样
     aggregate 使用复杂,但功能强大,功能上可以代替reduce和fold,计算效率上三者一致
   

     distinct去重

     sortBy 排序 ----- 单个分区排序 输入是原rdd的元素,而输出是排序的依据,算子是把x转换成排序条件
                       如果数据量小,想进行全排序,只需要把numPartitions设置成1即可
                       如果数据量大,想进行全排序,需要自定义parititoner保证分区间有序,然后再用sortby保证单分区有序
     
     takeOrdered :升序取topN
     top:         降序取topN
 
     分组
     groupBy  输入是每一个元素,输出是分组条件
              分组一般是为了计算,分组计算在pairRDD里面提供更高效的方式来进行,而且分组容易倾斜,所以尽可能避免开使用该方法来对数据进行计算
     

集合操作 cartesian 两个rdd之间 笛卡尔乘积

        union      两个rdd 合集 不去重
        subtract   两个rdd 差集
        zip        两个rdd相应位置处的数据并成一个元组,形成一个新的rdd
        RDD[Int]  zip RDD[String] ---》 RDD[(Int,String)]  拉链操作
        

功能型: ---------------把rdd添加到缓存中,缓存中的rdd在被调用和转换时有利于提升速度

                       如果一个rdd在整个计算过程中会被用到多次,name最好把这个rdd cache到缓存中

        cache          它是persist的特例,它等同于persist(StorageLevel.MEMORY_ONLY)
        persist        根据级别来设置缓存的存储位置,

        ---------------暂存rdd中的数据到本地文件中(容错机制)
        checkpoint
        分区一般在rdd执行了filter,flatmap,聚合等操作之后对新的rdd进行的一种操作,目的是调整下一步计算的平行度,和数据均衡
        repartition ---- 重分区,使用宽依赖的方式
        coalesce    ---- 重分区,可以选择使用窄依赖的方式  

读值型: collect

        count
        countByValue
        take(n) -----取出前N条数据发送到driver 一般应用于开发测试

数据模型资源手册
主题
数据模型工具:powerdesigner

          ea   uml

odi pdi kettle

flink storm

45 spark程序的数据处理过程,是在driver上来进行解析编译,在具体对数据处理的时候需要一个触发点来触发执行计算过程
这个触发点就是rdd的action方法

rdd的处理方法(函数)有两种
transformation 转换 对数据进行计算转换抽取,只记录处理过程而不真正计算数据,例如,一行变多行,一个单词变kv对,把一个key下的所有value累加
action 行为 对数据进行读值,触发对数据的计算过程,触发后会把action前面的所有的transformation启动执行,一般不改变数据,只是对数据的结果值进行读取

46 intellj中的程序直接运行在spark的standalone模式下
1.创建artifact(项目编译打包)
2.修改conf的master设置:val conf = new SparkConf().setMaster("spark://centos1:7077").setAppName("word count")
3.在sc下添加我们intellj打的包,打包过程,build---》build artifacts---》build:

 sc.addJar("D:\\javaproj\\sparkbd17\\out\\artifacts\\sparkbd17_jar\\sparkbd17.jar")

47 SparkContext
spark功能使用的主入口点
它负责连接spark 集群,并且在spark集群上创建RDD
,创建accumulators,broadcast variables(共享变量)

实例化方法:new SparkContext(conf) 多例

           SparkContext.getOrCreate(conf)   单例

SparkConf
实例化: new SparkConf()
实力化时如果不指定是否加载默认,它会加载默认配置文件,如:core-site.xml,hive-site.xml,hbase-site.xml,如果不想引入这些文件,可以:new SparkConf(false)
可以链式调用配置其参数
conf.set("","").set("","")
new SparkConf().setMaster("local").setAppName("My app")

构建RDD

       从hadoop体系相关的文件中获取数据组装成rdd
       binaryFiles()
       binaryRecords()
       hadoopFile()
       hadoopRDD()
       newAPIHadoopFile()
       newAPIHadoopRDD()
       sequenceFile()
       textFile()
       wholeTextFiles()
       objectFile()
       从内存中获取数据,组装成rdd
       makeRDD()
       parallelize()


创建累加器:
       register(acc: AccumulatorV2[_, _], name: String)

       doubleAccumulator(name: String)
       collectionAccumulator[T]
       longAccumulator(name: String)
创建广播变量
       broadcast[T](value: T)(implicit arg0: ClassTag[T])

默认最小分区数:defaultMinPartitions
部署模式:deployMode

48 RDD
1.它有一组分区构成,不同的分区在不同的集群节点上
2.可以通过调用它的方法(transformation和action),来对rdd的每一个分区进行各自计算(对rdd进行分布式计算)
3.RDD之间是有依赖关系的,在spark中很少有rdd的独立的

4.对于kv对的rdd可以使用分区器Partitioner来对其进行分区
5.在对文件进行加载的时候,它会优先在拥有文件的节点上启动加载executor
49 RDD容错
rdd是通过依赖关系(DAG)来容错的

50 RDD api

转换型

      flatMap   ----- 一输入对多输出  输入是元素,输出是集合对象
      map        ----- 一个输入对应一个输出,如果没有返回,对应元素的返回值会是()
  mapPartitions ----- 一个输入分区对应一个输出分区,新老rdd之间的元素可以不用一对一
     keyBy     ----- 输入一个元素x输出一个kv,v就是原来的元素,k是由x经过算子计算而来,算子把x转成k

聚合型

     aggregate
     
     聚合计算函数:
     reduce 方便使用,只需要定义一个迭代算子,聚合结果的类型要和原rdd的泛型中的数据类型保持一致
     fold   比reduce多了一个初值的指定,其他的和reduce一样
     aggregate 使用复杂,但功能强大,功能上可以代替reduce和fold,计算效率上三者一致
   

     distinct去重

     sortBy 排序 ----- 单个分区排序 输入是原rdd的元素,而输出是排序的依据,算子是把x转换成排序条件
                       如果数据量小,想进行全排序,只需要把numPartitions设置成1即可
                       如果数据量大,想进行全排序,需要自定义parititoner保证分区间有序,然后再用sortby保证单分区有序
     
     takeOrdered :升序取topN
     top:         降序取topN
 
     分组
     groupBy  输入是每一个元素,输出是分组条件
              分组一般是为了计算,分组计算在pairRDD里面提供更高效的方式来进行,而且分组容易倾斜,所以尽可能避免开使用该方法来对数据进行计算
     

集合操作 cartesian 两个rdd之间 笛卡尔乘积

        union      两个rdd 合集 不去重
        subtract   两个rdd 差集
        zip        两个rdd相应位置处的数据并成一个元组,形成一个新的rdd
        RDD[Int]  zip RDD[String] ---》 RDD[(Int,String)]  拉链操作
        

功能型: ---------------把rdd添加到缓存中,缓存中的rdd在被调用和转换时有利于提升速度

                       如果一个rdd在整个计算过程中会被用到多次,name最好把这个rdd cache到缓存中

        cache          它是persist的特例,它等同于persist(StorageLevel.MEMORY_ONLY)
        persist        根据级别来设置缓存的存储位置,

        ---------------暂存rdd中的数据到本地文件中(容错机制)
        checkpoint     -----   数据冷备份
                               它会把rdd的数据持久化到文件系统(本地文件系统,hdfs)
        分区一般在rdd执行了filter,flatmap,聚合等操作之后对新的rdd进行的一种操作,目的是调整下一步计算的平行度,和数据均衡
        repartition ---- 重分区,使用宽依赖的方式
        coalesce    ---- 重分区,可以选择使用窄依赖的方式  

读值型: collect ----- 把rdd的数据搜集到driver

        count
        countByValue
        take(n) -----取出前N条数据发送到driver 一般应用于开发测试

        foreach ----- action 遍历rdd,这个是每个分区各自执行,每条记录执行一次算子
        foreachPartition ----- action,遍历rdd,每个分区执行一次算子
        

        saveAsObjectFile  ----- action
        saveAsTextFile  ----- action

分区器获取 partitioner
分区对象 partitions
依赖关系 dependencies

51 pairRdd
如果一个rdd的每一个元素都是一个元组,并且这个元组只有两个元素,那么这个rdd会被隐式转换成pairrdd
RDD[(Int,String)],RDD[(Int,List[String])],RDD[(Int,(Int,String,Double))]
下面不是pairrdd
RDD[(Int,Int,String)]

---转换 flatMapValues ----- 算子输入,rdd的value 输出:集合对象,集合中每个元素都会和原来的key组装成1个新的rdd的kv

     mapValues  ----- 算子输入,rdd的value 输出:新的value,新的value和原来的key构成新的kv
     
     keys       --- 把kvrdd的key抽出来作为新的rdd
     values     --- 把kvrdd的value 抽出来做为新的rdd

---聚合 reduceByKey 应用简单方便,计算效率高,但是需要聚合值和kv对的value的类型保持一致

     foldByKey     和reduceByKey的区别在于,需要指定一个初始值,每个value经过计算的计算过程都一样,其余和reduceByKey
     aggregateByKey 比较灵活,功能强大,计算效率高,没有聚合值需要和value类型保持一致的限制
     combineByKey   它和aggregateByKey基本一样,不同点在于初值的获取方式,aggregateByKey的初值是作为参数我们直接指定
                    combineByKey的初始值需要我们定义一个函数,由这个函数来生成初始值,它的输入是迭代计算的第一个元素
    ----------------------------------------------------------------------------------------------
     groupByKey    对kv的rdd进行分组,按照key把同一个key下的所有value放入一个集合对象中,和key形成一个新的kv
     
     cogroup       对多个rdd中的数据按照key进行分组,key相同的属于多个rdd之间的value都会被打包到一个集合对象中,然后形成一个元组
                   这个元组会和key形成一个新的kv来作为结果的一条记录

---集合操作 subtractByKey 根据key值减去rdd中的kv对记录

      
     关联操作
     join                     内关联   两个rdd根据key相互排除
     leftOuterJoin            左边对象 为主表 根据key去排除右边对象的元素值,然后关联
     rightOuterJoin           右边对象 为主表 根据key去排除左边对象的元素值,然后关联
     fullOuterJoin            连个rdd相互补充形成新的rdd

---action
lookup 根据key值,获取rdd中所有key等于查询值的结果

       如果rdd是根据key来进行分区的话,那么lookup会根据分区器定位查询条件所在的分区,减少扫描数据量,提高查询效率

collectAsMap 把rdd转换成map

              如果rdd中一个key会有多个value,那么转换成的map中,一个key只保留其中一个value

countByKey 计算每一个key对应的元素的个数

--- 保存输出(action)
saveAsHadoopDataset
saveAsHadoopFile ----老本版hadoop操作的api
saveAsNewAPIHadoopDataset 把rdd的数据保存到hbase的方法
saveAsNewAPIHadoopFile 把rdd的数据按照指定的格式保存到hdfs上
saveAsSequenceFile 把rdd的数据以sequenceFile的格式保存到hdfs

52 共享变量
累加器 accumulator

      在driver上定义 在executor上写
      accumulator对executor来说是只写的
      
      只有在driver上才能读取出accumulator的正确值
      

广播变量 broadcast variable

      在driver上定义赋值,在executor读取使用
      broadcast variable对executor来说是只读的
      
      一般在driver上计算或者获取某个值,然后广播给每个executor来使用

53 spark读写mysql
JdbcRDD 通过实例化JdbcRDD对象来完成对关系型数据库中的数据作为spark数据源的一种方式
实例化的过程需要:SparkContext

                 关系型数据库的连接
                 sql 必须要包含2个问号
                 lowbound  highbound 分别和sql中的2个问号对应
                 partitionNum
                 结果转换函数:r=>r  从关系型数据库里获取的数据是resultset,那在读取进来的rdd中希望他是什么类型就用这个函数来完成转换
                  

54 写数据到hbase中
1.添加hbase依赖

 
  org.apache.hbase
  hbase-client
  1.2.3


  org.apache.hbase
  hbase-server
  1.2.3

2.hbase配置 hbase-site.xml
3.构建写入hbase的job(这个是mapreduce job)

 val job = Job.getInstance(configuration)
 在job中配置往hbase中写数据的各种配置信息,与mr写hbase一样

4.把rdd转换成kv,必须保证v的类型是(Mutation类型)Put类型或者Delete类型
5.调用saveAsNewAPIHadoopDataset,同时把job的配置信息当做参数

 hbaseResult.saveAsNewAPIHadoopDataset(job.getConfiguration)
 

55 spark从hbase中读取数据加载成RDD
使用sparkContext的newAPIHadoopRDD方法,以mr的InputFormat的方式从hbase中加载数据
需要指定读取数据的inputformat为:TableInputFormat

                 key的类型:ImmutableBytesWritable
                 value的类型:Result

rdd从hbase读取的数据每一行会作为rdd的一个元素,类型为Result
可以使用result的cellScanner对数据进行取值
也可以使用getColumn等hbase的api方法从result中取值

56 spark程序发布运行模式
hadoop发布运行(hadoop jar)
hive发布程序运行(hive -f hive脚本位置)
发布程序需要使用spark-submit指令
spark-submit [options] [app arguments]

--class 应用程序主函数入口类的指定
--jars 指定应用程序的运行的依赖jar包的位置

       一般情况下我们可以在应用程序里面使用sc.addJar方法指定hdfs上的jar加载应用程序的依赖jar

--master 发布运行模式

local ---本地模式运行 local[n],local[*]

standalone

     --deploy-model client/cluster
     client模式,driver程序是运行在client上,哪里submit的spark程序,哪里就是client,要等集群中所有的计算都结束spark-submit才会结束
     cluster模式,是driver程序运行在集群中的某个工作节点上,客户端那里只要提交任务成功spark-submit就已经结束了
     

yarn

     部署模式也是分成两种client和cluster
     运行结构也和standalone一样

mesos

--deploy-mode 部署模式,除了local之外standalone,yarn,mesos都有两种部署模式:cluster、client
--conf 运行时环境参数 比方说运行时内存设置,运行时executor数量设置等

本地模式运行
spark-submit --class com.zhiyou.bd17.WordCount --master local sparkbd17.jar
standalone模式运行
spark-submit --master spark://centos1:7077 --deploy-mode client --class com.zhiyou.bd17.WordCount sparkbd17.jar
spark-submit --master spark://centos1:7077 --deploy-mode cluster --class com.zhiyou.bd17.WordCount sparkbd17.jar
yarn运行模式
spark-submit --master yarn --deploy-mode client --class com.zhiyou.bd17.WordCount sparkbd17.jar
spark-submit --master yarn --deploy-mode cluster --class com.zhiyou.bd17.WordCount sparkbd17.jar

--------yarn的client模式下如果因为内存不够抛异常

    在yarn-site.xml把yarn.nodemanager.vmem-check-enabled设置为false重启yarn,在submit-spark程序
    
    yarn.nodemanager.vmem-check-enabled
            false

57 java的spark开发
1.构建maven项目
2.添加spark依赖
3.构建JavaSparkContext
4.使用JavaSparkContext构建JavaRDD
5.对JavaRDD调用transformation和action 操作数据(大量的内部类写法实例化算子)
6.计算结束,停用sparkcontext:sc.stop()

58 spark sql
它是对spark的扩展和优化,让我们增添了一种新的使用spark进行数据处理的方式
1.sql 处理
2.linq api(Dataset)处理

解释器---》优化器---》执行器---》spark rdd执行完成对数据处理
兼容hive 的metastore、serder、udf等

59 scala项目的maven创建
new--->maven project-->不使用模板--->在pom中添加:
依赖:

    
        org.scala-lang
        scala-library
        2.11.8
    

插件:

    
        
            
            net.alchim31.maven
            scala-maven-plugin
            3.1.3
            
                
                    
                        compile
                        testCompile
                    
                    
                        
                            -dependencyfile
                            ${project.build.directory}/.scala_dependencies
                        
                    
                
            
        
        
            org.apache.maven.plugins
            maven-surefire-plugin
            2.13
            
                false
                true
                
                
                
                    **/*Test.*
                    **/*Suite.*
                
            
        
    


在src下新建一个scala目录
projcet structure--->modules--->选中scala目录--->点击Sources按钮,把scala目录设置成源文件目录

60 spark编程模型

1.SparkConf-->SparkContext --> RDD -->RDD调用transformation和action
2.SparkSession --> DataSet/DataFrame -->直接调用sql后者调用DS/DF的 transformat和action linq模式取数据方法
3.SparkConf-->StreamingContext --> DStream -->对DStream调用transformation和action 以及窗口window计算函数

61 程序

val spark = SparkSession.builder().master("local[*]").appName("spark sql world count").getOrCreate()
import spark.implicits._
import spark.sql
ds.createOrReplaceTempView("line_str")
sql("select * from line_str")

shark(hive on spark)

explain select * from aaa

数据模型资源手册
主题
数据模型工具:powerdesigner

          ea   uml

odi pdi kettle

flink storm

项目类型:
管理类型的

    oa
    mis
    财务系统
    人力资源系统
    生产管理(erp)
    业务管理系统    产权产籍管理系统
                    行政中心收费系统
                    ----------------
                    消防中心管理系统
                    培训管理系统

互联网类型

    电商平台
    cms

数据分析类型

    经营分析
    用户行为分析
    风险监控平台
    业务分析------  旅游住宿大数据平台
    日志分析

大数据项目

    数据采集
    数据处理分析
    数据存储
    etl,数据分析自动化执行的框架或者技术 oozie azkaban kettle (odi oracle的)
    数据展现
    

web 项目

   整体架构
   mvc springmvc struts2
   依赖注入   sparing
   orm   hibernate mybatis
   数据库 mysql oracle postgresql sqlserver
   前端(js)框架:jquery bootstrap ajax           angular  vue  react
   模板技术   jsp  freemarker volicity theamleaf
   服务器  tomcat jetty apache nginx
   缓存(缓存session信息和一些常用字典信息)   redis  ehcache       
   springboot  
   分布式服务治理:springcloud  dubbo 

项目描述

   项目背景    项目为谁做的
               为什么要做这个项目
               这个项目解决了什么问题 
               达到什么目标
   项目需求概述
               项目的基本业务需求  招标流程管理                            对诊疗数据进行汇总分析提取医院和疾病等的花费、耗时等指标信息    
               项目的业务模块      采购管理,审批管理模块 竞标管理 中标发布            医院主题分析  疾病主题分析   医生主题分析  报销主题分析
   项目基本技术架构
               主要采用 flume来做日志数据采集,使用mr和hive来进行需求报表计算,用ssm构建web应用展示数据报表

责任描述:

   在项目主要使用什么技术,来进行什么需求的开发
     我在项目中主要使用hive+sql编写数据处理分析过程,完成对需求报表的开发,同时还负责调度的运行维护,以及数据处理程序的优化工作
   项目中主要做:1,具体的业务需求
                 2,完成采购管理模块 审批管理模块的开发
                 3,完成医院主题分析中医院治愈率报表,消费水平报表等开发
                 4
                 。。。。。

你可能感兴趣的:(scala,数据库,测试)