点击关注上方“知了小巷”,
设为“置顶或星标”,第一时间送达干货。
Spark技术栈-Scala
Scala combines object-oriented and functional programming in one concise, high-level language. Scala's static types help avoid bugs in complex applications, and its JVM and JavaScript runtimes let you build high-performance systems with easy access to huge ecosystems of libraries.
1. Scala的偏函数
偏函数,即Partial Function,是数学概念,它不是“函数”的一种,它跟函数是平行的概念。Scala中的Partial Function是一个Trait,类型为PartialFunction[A,B],其中接收一个类型为A的参数,返回一个类型为B的结果,它是一个一元函数(a unary function)。
trait PartialFunction[-A, +B] extends (A => B) { self =>
import PartialFunction._
def isDefinedAt(x: A): Boolean
def orElse[A1 <:>A, B1 >: B](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] =new OrElse[A1, B1] (this, that)override def andThen[C](k: B => C): PartialFunction[A, C] =new AndThen[A, B, C] (this, k)def lift: A => Option[B] = new Lifted(this)def applyOrElse[A1 <:>A, B1 >: B](x: A1, default: A1 => B1): B1 =if (isDefinedAt(x)) apply(x) else default(x) def runWith[U](action: B => U): A => Boolean = { x =>val z = applyOrElse(x, checkFallback[B])if (!fallbackOccurred(z)) { action(z); true } else false
}
}
简单举例:可以理解为枚举或者K-V或者case .. default
scala> val pf:PartialFunction[Int, String] = {
| case 1=>"One"
| case 2=>"Two"
| case 3=>"Three"
| case _=>"Other"
|}
}
pf:PartialFunction[Int, String] =
scala> pf(1)
res0: String = One
scala> pf(2)
res1: String = Two
scala> pf(3)
res2: String = Three
scala> pf(4)
res3: String = Other
2. Scala的柯里化
柯里化函数也叫做多参数列表函数,本身就是指把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
简单理解就是改变函数的形式,不改变函数的功能。就是把多元函数变换为一元函数。
def add(x:Int,y:Int)=x+y
add(1,2)
def add(x:Int)(y:Int) = x + y
add(1)(2)
上面从add(1,2) ==> add(1)(2)就是柯里化。实现过程:
add(1)(2) 实际上是依次调用两个普通函数(非柯里化函数),第一次调用使用一个参数 x,返回一个函数类型的值,第二次使用参数y调用这个函数类型的值。
def add(x:Int)=(y:Int)=>x+y
接收一个x为参数,返回一个匿名函数,该匿名函数的定义是:接收一个Int型参数y,函数体为x+y。
// result: (y:Int)=>1+y
val result = add(1)
// 2 + 1
val sum = result(2)
3. Scala的apply和unapply方法是什么作用?
apply:通常,在一个类的伴生对象中定义apply方法,在生成这个类的对象时,就省去了new关键字。unapply:可以认为unapply方法是apply方法的反向操作,apply方法接受构造参数变成对象,而unapply方法接受一个对象,从中提取值(成员变量)。
4. Scala的元组定义之后可变吗?
元组在Scala语言中是一个非常有用的容器对象。与列表一样,元组也是不可变的;但是与列表不同,元组可以包含不同类型的元素。例如,列表只能写成List[Int]或者List[String],但是元组可以同时拥有Int和String。元组适用场景很多,比方说,如果需要在方法里返回多个对象。Java里的做法是创建JavaBean用来包含多个返回值,Scala里可以直接返回元组(翻版的Map,只是Key是顺序数字)。主要是用起来也很简单;只要把元组实例化需要的对象放在括号里,并用逗号分隔即可。元组实例化之后,可以用点号、下划线和基于1的索引访问其中的元素。目前Scala支持的元组最大长度为22。对于更大长度可以使用集合,或者扩展元组。
5. Java VS Scala
Scala来源于Java,又“高于”Java,在Java之上增加了一层编码的“API”,让程序员可以通过函数式编程的方式来开发程序。
Scala程序最终被编译为.class文件运行在JVM虚拟机中,所以它是JVM下的语言一种,其他的还有Groovy等。
区别
- 变量声明
- var变量;val常量;Scala支持自动类型推断
- Scala更多的是采用常量,而不是变量来解决问题,这样带来的好处是可以减少多线程并发安全问题,特别适合高并发分布式的场景。
- 函数的声明
- 关键字def,Scala函数没有返回值时使用Unit,相当于Java的void。
- Scala支持函数式编程,可以使用高阶函数,函数是一等公民。
基本类型
Scala中没有真正意义上的基本类型,类型都是类。静态
- Java中静态static是违背Java OOP编程思想和封装特性。
- Scala取消了静态的概念,使用了单例对象Object来实现。
- 字符串
- Scala支持使用字符串插值的方式对字符串进行格式化,使用$开头进行取值。
- 另外支持使用三引号将其中的内容直接包起来(Python也有三引号),其中可以包括任何字符,而不需要进行特别转义。
- 类
- Scala类中的字段自动带有getter和setter方法,另外可以使用@BeanProperty注解来生成Java中的Get/Set方法。
- Scala中的每个类都有一个主构造方法,这个构造方法和类定义“交织在一起”,类的参数直接成为类的字段,主构造方法执行类体中的所有语句。
- Scala中不支持break
- 使用return替代
- 在循环中使用if和布尔类型变量
- 导入Java中支持break的包
- 访问范围
- Java中外部看不到内部,内部能看到外部
- Scala中外部看不到内部,内部也看不到外部
- 通配符
- Java中使用* 进行通配
- Scala中使用_ 进行通配
- 默认导入的类
- Scala默认java.lang包、Scala包、Scala.Predef类
- Java默认导入java.lang包
- 特质trait可以类比Java中的接口,但是和接口非常不一样
- Java中称为 类实现了接口,Scala中称为 混入了特质
- 和Java中的接口不同,Scala中的特质可以包含带有方法体的方法(JDK8接口也可以的,比如default方法)。
6. Scala有哪些优点?
- Scala是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。
- Scala运行在JVM上,并兼容现有的Java程序。
- Scala源代码被编译为Java字节码,所以可以运行在JVM上,并可以调用现有的Java类库。
- 作为流行的开源大数据内存计算引擎Spark的源码编程语言,Spark有着良好的性能优势。
- Scala将成为未来大数据处理的主流语言。(Java也挺多,Python也可以)
7. Scala中的隐式函数
关键字:implicit
Scala在面对编译出现类型错误时,提供了一个由编译器自我修复的机制,编译器试图去寻找一个隐式implicit的转换方法,转换出正确的类型,完成编译,这就是implicit的意义。
8. val x=y=1 会报错
9. 编译好的Scala程序,运行时还需要Scala环境吗?
不需要
10. trait特质和abstract class(抽象类)的区别?
- 一个类只能继承一个抽象类,但是可以通过with关键字继承多个特质
- 抽象类有带参数的构造函数,特质不行
一个类混入多个特质是很方便的,但却只能扩展一个抽象类。所以优先使用特质,如果需要构造函数参数,则使用抽象类。
11. Scala数据类型有哪些?
Byte、Short、Int、Long、Float、Double、Char、String、Boolean、Unit、Null、Nothing、Any。
Any是所有类的超类。
AnyRef类是Scala里所有引用类reference class的基类。
12. Scala中String对象是可变的还是不可变的?假如要创建一个可以修改的字符串,应该使用哪个类?
Scala本身没有String,依然是Java String,当然是不可变的。
可变的话,依然是StringBuilder或StringBuffer。
13. Scala的闭包
闭包是一个函数,返回值依赖于声明在函数外部的一个或多个变量。
闭包的实质是代码与用到的非局部变量的混合,即:闭包 = 代码 + 用到的非局部变量。
var y = 1
val sum = (x: Int) => x + y
println(sum(1)) // 结果为2
y = 10
println(sum(1)) // 结果为11
14. 函数中的Unit
Scala中的Unit类型类似于Java中的void,没有返回值。主要的不同是在Scala中可以有一个Unit类型值,也就是();然而Java中是没有void类型的值的。除此之外,Unit和void是等效的。一般来说每一个返回void的Java方法对应一个返回Unit的Scala方法。
15. val a = 10,怎样将a转为double类型,String类型
a.toString
a.toDouble
16. ArrayBuffer和Array的区别
- 数组里面可以放数字、字符串、布尔值以及对象和数组等,ArrayBuffer放0和1组成的二进制数据
- 数组放在堆中,ArrayBuffer则把数据放在栈里面(取数更快)
ArrayBuffer初始化后固定大小,数组可以自由增减
数据中台实战系列笔记
浅谈OLAP系统核心技术点(建议收藏)
HBase基础面试题总结
Hive基础面试题总结
MapReduce和YARN基础面试题总结
HDFS基础面试题总结