Spark学习记录(一)
一、介绍
scala 是一门以 jvm 为运行环境的静态类型编程语言,具备面向对象及函数式编程的特性。
1.1、Scala的六大特性
- Java 和 scala 可以混编
- 类型推测(自动推测类型)
- 并发和分布式( Actor )
- 特质,特征(类似 java 中 interfaces 和 abstract 结合)
- 模式匹配(类似 java 中的 switch...case )
- 高阶函数
1.2、应用场景
kafka :分布式消息队列,内部代码经常用来处理并发的问题,用scala可以大大简化其代码。
spark :方便处理多线程场景,另外 spark 主要用作内存计算,经常要用来实现复杂的算法。利用
scala 这种函数式编程语言可以大大简化代码
1.3、相关网站
scala官网:https://spark.apache.org/
查看spark和scala: https://spark.apache.org/docs/
1.4、开发环境搭建问题
1.4.1使用idea(社区版)开发
idea的社区版已经包含了Scala开发的基本功能,Scala+maven的方式开发spark程序。
1.4.2、使用vscode开发
(!重点!)使用 VS Code 搭建 java + scala 开发环境:https://blog.csdn.net/tangliyong2012/article/details/125172099
spark运行在windows环境的idea遇到的问题记录:https://blog.csdn.net/wangsg2014/article/details/122697958
VS Code下的Spark(Scala)开发:https://blog.csdn.net/lyd882/article/details/111638953
安装下面三个插件:
二、基础
2.1、数据类型
Scala的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。
Scala 数据类型分为两大类 AnyVal(值类型) 和 AnyRef(引用类型)!
不管是 AnyVal 还是 AnyRef 都是对象
- Any 是所有类的根类型,即所有类的父类(基类)。
- 在 scala 中类分为两个大的类型分支(AnyVal [值类型,即可以理解成就是 java 的基本数据类型],AnyRef 类型[引用类型])。
- 在 AnyVal 虽然叫值类型,但是仍然是类(对象)。
- 在 scala 中有两个特别的类型(Null ), 还有一个是 Nothing。
- Null 类型只有一个实例 null, 是 AnyRef 的子类,类似于Java中的null引用,null可以赋值给任意的引用类型,但是不可以赋值给值类型。
- Nothing 类型是所有类的子类, 它的价值是在于因为它是所有类的子类,就可以将 Nothing 类型的对象返回给任意的变量或者方法,可以作为没有正常返回值的方法的返回类型。
- 在 scala 中仍然遵守 低精度的数据自动的转成高精度的数据类型,称为:自动类型转换(隐式转换 implicit conversion)
- 在 scala 中,Unit 类型比较特殊,这个类型也只有一个实例 ()。Unit 类型用来标识过程,也就是没有明确返回值的函数。由此可见,Unit 类似于 Java 里的 void。
- byte,short,char 他们三者可以计算,在计算时首先转换为 Int 类型。
2.2、变量和常量
var修饰的是变量
val修饰的是常量(定义之后不可以修改)
2.3、循环
1、(a to (b , c)).foreach(println)
to 包含b
2、(a until (b , c )).foreach(println)
until 不包含b
3、Array.range(a,b,c).foreach(println)
4、普通for循环
for( i <- 1 to 10;if i%2==0){ println(i) }
5、yield
// 方式1 var a = 0 val numList = List(1,2,3,4,5,6,7,8,9,10) var retVal = for{ a <- numList if a %2 == 0 }yield a retVal.foreach(println) // 方式2,格式简单,内容清晰 var list = for(i <- 1 to 10 ;if i%2 !=0)yield i list.foreach(println)
2.4、方法与函数
2.4.1、方法的定义
def functionName ([参数列表]) : [return type] = { function body return [expr] }
- 在参数后面加一个冒号和类型来显式地指定返回类型。
2. 方法可以写返回值的类型也可以不写,会自动推断,但是如果有显式的Return有时候不能省略,必须写。
3. Scala 中函数有返回值时,可以写 return ,也可以不写 return ,不写 return 时会把函数中最后一行当做结果返回。
//直接等于 def function(a:Int,b:Int) = a+b // Unit代表无返回值 def function2(a:Int,b:Int):Unit={ println(a+b) } // 返回值类型自动推断 def function3(a:Int)={ return a }
2.4.2、函数
在Scala中方法和函数不是同一个东西。
Scala 方法是类的一部分,而函数是一个对象,对象的引用可以赋值给一个变量。换句话来说在类中定义的函数即是方法。
def定义方法,val定义方法!
def m(x: Int) = x + 3
val f = (x: Int) => x + 3
方法和函数的区别:
- 当函数定义在类中,就表示方法,其他的都称为函数。
- 函数可以作为一个参数传入到方法中,而方法就不行。
- 在需要函数的地方,如果传递一个方法,会自动进行ETA展开(把方法转换为函数)。
- 函数必须要有参数列表,而方法可以没有参数列表。
- 如果我们直接把一个方法赋值给变量会报错。
2.5、类和对象
2.5.1、构造函数
- 每个类都有一个主要的构造器,这个构造器不是单独声明的构造函数,而是和类定义交织在一起。
- 当你阅读一个Scala类时,你需要将它们分开理解,一个是类的定义,一个是构造函数的定义。
- 除了主构造器之外,类还可以有任意多的辅助构造器(auxiliary constructor)。辅助构造器的名称为this
- 每一个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始
class User{ var name = "" var age = "" var address = "" def this(name:String) = { this() this.name = name } def this(name:String,age:Int) = { this(name) this.age = age } def this(name:String,age:Int,address:String) = { this(name,age) this.address = address }
2.6、继承
和Java一样的,Scala中也是单继承,只能有一个父类。需要遵循下面几点:
- 重写一个非抽象方法必须使用override修饰符。
- 只有主构造函数才可以往基类的构造函数里写参数。
- 在子类中重写超类的抽象方法时,你不需要使用override关键字。
// 父类 abstract class Person{ def eat():Unit def say():String } class Student extends Person{ def eat()={ println("学生去食堂吃饭") } def say():String={ "不想上课" } def study()={ println("学生的任务是学习") } } class HghSchoolStudent extends Student{ // 因为父类不是抽象类,所以重写父类的方法需要加上override override def study(): Unit = { println("马上要高考啦!") } }
2.7、trait(特征)
- Scala 中 Trait (特征) 相当于 Java 的接口,实际上它比接口还功能强大。
- 与接口不同的是,它还可以定义属性和方法的实现。
- 一般情况下Scala的类可以继承多个 Trait ,从结果来看就是实现了多重继承。 Trait (特征) 定义的方式与类类似,但它使用的关键字是 trait 。
object Main { def main(args :Array[String]):Unit={ val person = new Person person.write("人生") } } trait Read{ val readType = "" val gender = "" def read(name :String)={ println("要读的书的名字是:"+name) } } trait Write{ val writeType = "" val gender = "" def write(name :String)={ println("要写的书的名字是:"+name) } } // 类似于Java中实现了多接口 class Person extends Read with Write{ override val gender: String = "" }
- 继承的多个trait中如果有同名的方法和属性,必须要在类中使用 override 重新定义。trait 中不可以传参数
- trait中带方法实现