大数据—— Scala 知识点整理

目录

 

1. Scala 语言的优点

2. Scala 中的闭包

3. Scala 中的柯里化

4. Java 和 Scala 的联系和区别

5. Scala 中的模式匹配

6. case class 和 class 的区别

7. 谈谈 Scala 中的隐式操作

8. Scala 中的偏函数和偏应用函数

9. Scala 中的元组

10. trait(特质)和 abstract class(抽象类)的区别

11. ArrayBuffer 和 Array 的区别


1. Scala 语言的优点

  • Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性
  • Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序
  • Scala 源代码被变编译成 Java 字节码,所以它可以运行于 JVM之上,并可以调用现有的 Java 类库
  • 作为流行的开源大数据内存计算引擎 Spark 的源码编程语言,Spark 有着良好的性能优势
  • Scala 将成为未来大数据处理的主流语言

2. Scala 中的闭包

        定义:可以在任何作用域内定义函数、包、类甚至是另一个函数或方法。在函数体内,可以访问到相应作用域内地任何变量。(重点)函数可以在变量不再处于作用域内时被调用。

object Test {
 
  /**
    * scala中的闭包
    * 函数在变量不处于其有效作用域内,还能够对变量进行访问
    *
    * @param args
    */
 
  def main(args: Array[String]): Unit = {
 
    def getHelloFunc(msg:String) = (name:String) => println(msg + "," + name)
 
    val sayHello = getHelloFunc("hello") // 传入msg的值 ,后面sayHello依然可以访问到
    val sayHi = getHelloFunc("hi")
 
    // 两次条用getHelloFunc,传入不同的msg,创建不同的函数返回
    // 然而msg只是一个局部变量,
    // 在getHelloFunc调用后,还继续存在创建的函数中,当sayHello("yxj")调用时,值为hello的msg保留在了函数内部,可以反复使用
    // 这种变量超出了其作用域,还可以使用的情况,就是闭包
 
    // scala
 
    sayHello("yxj") // 打印 hello,yxj
    sayHi("yxj") // 打印 hi,yxj
 
  }
}

3. Scala 中的柯里化

        柯里化函数也叫多参数列表函数,本身就是指把接受多分参数的函数变化成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术

        简单理解就是改变函数的形式,不改变函数的功能。用途:和隐式参数结合使用大大简化代码,但降低了代码的可读性

//该函数接受两个参数
def mul(x:Int,y:Int) = x*y

//该函数接受一个参数生成另外一个接受单个参数的函数
def mulOneAtTime(x:Int)(y:Int) = x*y

//也可以写成
def mulOneAtTime(x:Int) = (y:Int) => x * y

4. Java 和 Scala 的联系和区别

联系:

  • Scala 源于 Java,但又高于 Java,Scala 在 Java 的基础上增加了函数式编程,让开发人员可以通过函数式编程来开发程序
  • 由于 Scala 最终被编译为 .class 文件运行在 JVM 中,其实本质上还是 Java,所以在 Scala 和 Java 可以互调双方的 API

区别:

  • 变量的声明: 
    • 变量 var 常量 val,Scala 支持自动类型推测
    • Scala 更多的是采用常量而不是变量来解决问题,好处是可以减少多线程并发的安全问题,特别适合用于多并发分布式的场景
  • 函数的声明
    • 关键字 def,Scala 函数没有返回值用 Unit,相当于 Java 中的 void
    • Scala 支持函数式编程,可以使用高阶函数,函数在 Scala 中是一等公民
  • 基本类型
    •  Scala 是存粹的面向对象的编程语言,所以并没有真正意义上的基本类型,他的类型都是类
  • 静态
    • Java 中静态 static 是违背 Java 面向对象的编程思想和封装特性的
    • Scala 取消了静态的概念,使用单例对象 object 来实现
  • 对字符串的支持
    • Scala 支持使用字符串差值的方式对字符串进行格式化,使用$开头进行取值
    • 另外支持使用三引号将其中的内容直接包起来,其中可以包括任何字符而不需要转义
    • 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 中的特质可以包含带有方法体的方法

5. Scala 中的模式匹配

        Scala 的模式匹配包括了一系列的备选项,每个替代项以关键字大小写为单位,每个替代方案包括一个模式或多个表达式,如果匹配将进行计算,箭头符号 => 将模式与表达式分离

        Scala中的模式匹配类似于Java中的switch语法,但是更加强大。 模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _ 分支,类似于Java中default语句。

 obj match{

        case 1 => "one"

        case 2 => "two"

        case 3 => "three"

        case _ => default

      }

6. case class 和 class 的区别

case class 是一个样例类:

        样例类是一种不可变切可分解类的语法糖,也就是说在构建的时候会自动生成一些语法糖,具有以下几个特点:

  • 自动添加与类名一致的构造函数(也就是半生对象,通过apply方法实现),也就是说在构造对象的时候不需要使用new关键字
  • 样本类中的参数默认是val关键字,不可以修改
  • 默认实现了toString,equals,hashcode,copy方法
  • 样本类可以通过==来比较两个对象,不在构造方法内地二属性不会用在比较上

class是一个类:

class在构造对象的时候需要使用new关键字才可以。

7. 谈谈 Scala 中的隐式操作

(1)隐式变量

        为函数提供隐式参数(常和柯里化结合使用)

def method(name:String)(prefix:String="DEFAULT") = print(prefix + name)

implicit prefix:String="DEFAULT"
def method(name:String)(implicit prefix:String) = print(prefix + name)

(2)隐式函数

        给函数类型的参数提供默认值,

        同一作用域下同一种类型只能出现一个

         应用:隐式类型转换

def main(args: Array[String]): Unit = {
    //隐式函数,默认将字符串类型转换为整数类型
    //同一作用域下同一类型只能出现一个,也就是说该作用域下不能再将字符串类型隐式转换成其他类型
    implicit def fsi(v:String):Option[Int] = {
        val regexInt = "\\d+".r
        if (regexInt.pattern.matcher(v).matches){
            Some(v.toInt)
        }else{
            Option.empty
        }
    }
    val a:Option[Int]="abc"
    println(a)
}

(3)隐式类

        隐式扩展唯一构造参数指定的类型的功能

//功能:如果数组类型为Int类型则求和,否则输出字符串,以空格为间隔符	  
implicit class ArrExt[T](arr:Array[T]){
	    def c()={
	      if (arr.isInstanceOf[Array[Int]] ){
	        arr.asInstanceOf[Array[Int]].sum
	      }else if(arr.isInstanceOf[Array[String]]){
	        arr.asInstanceOf[Array[String]].mkString(" ")
	      }else{
	        throw new RuntimeException("unsupported array type")
	      }
	    }
	  }
	  def main(args: Array[String]): Unit = {
	    println(Array(1, 2, 5).c())
	    println(Array("aa", "bb", "cc").c())
	  }

(4)隐式对象

        扩展功能

//功能:根据传入的参数值类型自动实现对应类型的函数
 def main(args: Array[String]): Unit = {
	    trait A[T]{
	      def combine(arr:Array[T]):T
	      def empty:T
	    }
	    implicit object StrArrA extends A[String] {
	      override def combine(arr: Array[String]): String = arr.mkString(",")
	      override def empty: String = ""
	    }
	    implicit object IntArrA extends A[Int] {
	      override def combine(arr: Array[Int]): Int = arr.sum
	      override def empty: Int = 0
	    }

	    def combine[T](arr:Array[T])(implicit a:A[T]) = {
	      if (arr.isEmpty){
	        a.empty
	      }else{
	        a.combine(arr)
	      }
	    }
	    val arrStr: Array[String] = Array("aa", "bb", "cc")
	    val arrInt: Array[Int] = Array(1, 2, 3)
	    println(combine(arrStr))
	    println(combine(arrInt))
	  }

8. Scala 中的偏函数和偏应用函数

偏函数(Partial Function)

        是一个数学概念它不是"函数"的一种, 它跟函数是平行的概念。Scala中 的 Partia Function是一个 Trait,其的类型为 PartialFunction[A,B],其中接收一个类型为 A 的参数,返回一个类型为 B 的结果。

        通常结合模型匹配使用

scala> val pf:PartialFunction[Int,String] = {
     |   case 1=>"One"
     |   case 2=>"Two"
     |   case 3=>"Three"
     |   case _=>"Other"
     | }
pf: PartialFunction[Int,String] = <function1>
scala> pf(1)

res0: String = One


scala> pf(2)

res1: String = Two


scala> pf(3)

res2: String = Three


scala> newPF(4)

res3: String = Other

        偏函数内部有一些方法,比如isDefinedAt、OrElse、 andThen、applyOrElse等等。

偏应用函数(Partial Applied Function)

        也叫部分应用函数,跟偏函数(Partial Function)从英文名来看只有一字之差,但他们二者之间却有天壤之别。

        部分应用函数, 是指一个函数有n个参数, 而我们为其提供少于n个参数, 那就得到了一个部分应用函数,类似于柯里化

scala> def add(x:Int,y:Int,z:Int) = x+y+z
add: (x: Int, y: Int, z: Int)Int
scala> def addX = add(1,:Int,:Int) // x 已知

addX: (Int, Int) => Int


scala> addX(2,3)

res1: Int = 6


scala> addX(3,4)

res2: Int = 8


scala> def addXAndY = add(10,100,_:Int) // x 和 y 已知

addXAndY: Int => Int


scala> addXAndY(1)

res3: Int = 111


scala> def addZ = add(:Int,:Int,10) // z 已知

addZ: (Int, Int) => Int


scala> addZ(1,2)

res4: Int = 13

9. Scala 中的元组

  • Scala中的元组是一个固定数量的组合,本体可以作为一个参数传递
  • 元组可以容纳不同类型的数据
  • 元组是不可变的
  • 元组是有上限的,最多能有22个元素

10. trait(特质)和 abstract class(抽象类)的区别

  • 一个类只能继承一个抽象类,但是可一个通过 with 关键字继承多个特质
  • 抽象类有带参数的构造函数,特质不行(如 trait t(i: Int) {},这种声明是错误的)。
  • 一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。所以优先使用特质。如果需要构造函数参数,使用抽象类 

11. ArrayBuffer 和 Array 的区别

  • Array 里面可以放数字、字符串、布尔值、以及对象和数组等,ArrayBuffer 放 0 和 1 组成的二进制数据
  • Array 存放在堆中,ArrayBuffer 则把数据存放在栈中(所以取数据时后者快)
  • ArrayBuffer 初始化后固定大小,数组则可以自由增减(其实是生成了一个新数组)

 往期面试题整理:

《大数据——Java 知识点整理》 

《大数据——MySQL 知识点整理》

《大数据—— Hadoop 知识点整理》 

《大数据—— Hive 知识点整理》 

《大数据—— HBase 知识点整理》 

《大数据—— Spark Core 知识点整理》

《大数据——Flink 知识点整理》

  • 40
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 44
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vicky_Tang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值