`
flylynne
  • 浏览: 365247 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Scala

 
阅读更多

一、scala语言有什么特点?什么是函数式编程?有什么优点?

  1、scala语言集成面向对象和函数式编程(函数式编程关心数据的映射,命令式编程关心解决问题的步骤)

  2、函数式编程是一种典范,将电脑的运算视作是函数的运算。

  3、与过程化编程相比,函数式编程里的函数计算可以随时调用。

  4、函数式编程中,函数是一等功明。

二、scala中的闭包

  1、闭包首先有函数嵌套,内部函数引用外部函数的变量,然后返回一个函数

   例如:

      def mulBy(factor:Double) = (x:Double) => factor * x

      //开始调用

      val tripe = mulBy(3)

      val half = mulBy(0.5)

      println(tripe(14) + " " + half(14))

    这就是一个闭包

三、scala中的柯里化

   定义:柯里化指的是将原一个接受多个参数的函数转化为接受其中几个参数的函数。经常被用来处理高阶函数

   例如:

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

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

      这样的话,如果需要计算两个数的乘积的话只需要调用:

      mulOneAtTime(5)(4)

    这就是函数的柯里化

高阶函数指能接受或者返回其他函数的函数,scala中的filter map flatMap函数都能接受其他函数作为参数。

四、scala中的模式匹配

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

    例如:

      obj match{

        case 1 => "one"

        case 2 => "two"

        case 3 => "three"

        case _ => default

      }

五、case class和class的区别

    case class:

样本类是一种不可变且可分解类的语法糖,这个语法糖的意思大概是在构建时,自动实现一些功能。样本类具有以下特性:
(1)自动添加与类名一致的构造函数(这个就是前面提到的伴生对象,通过apply方法实现),即构造对象时,不需要new;
(2)样本类中的参数默认添加val关键字,即参数不能修改;
(3)默认实现了toString,equals,hashcode,copy等方法;
(4)样本类可以通过==比较两个对象,并且不在构造方法中定义的属性不会用在比较上。

代码示例

//声明一个样本类
case class MyCaseClass(number: Int, text: String, others: List[Int]){
 println(number)
}
//不需要new关键字,创建一个对象
val dto = MyCaseClass(3, "text", List.empty) //打印结果3

//利用样本类默认实现的copy方法
dto.copy(number = 5) //打印结果5

val dto2 = MyCaseClass(3, "text", List.empty)
pringln(dto == dto2) // 返回true,两个不同的引用对象
class MyClass(number: Int, text: String, others: List[Int]) {}
val c1 = new MyClass(1, "txt", List.empty)
val c2 = new MyClass(1, "txt", List.empty)
println(c1 == c2 )// 返回false,两个不同的引用对象

class:

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

Object是类的单例对象,开发人员无需用new关键字实例化。如果对象的名称和类名相同,这个对象就是伴生对象

scala没有static关键字,搞出了个object关键字来新建单例对象。在单例对象中的成员都是static的。所以要写util类一般都要用这个东西。

假设有object A 和 class A 两个同名了。这时候就可以说:object A是class A的“伴生对象”;class A是object A的“伴生类”。当一个object B没有同名的class B的时候,object B就叫“做独立对象”。

伴生带来的特权就是:它们可以互相访问私有成员。

class和object的区别:
1、单例对象不能用new来初始化。
2、单例对象不能带参数。
3、单例对象在第一次调用的时候才初始化。

Value classes 允许开发者安全的增加一个新类型,避免运行时对象分配。有一些 必须进行分配的情况 and 限制,但是基本的思想是:在编译时,通过使用原始类型替换值类实例,删除对象分配。

六、谈谈scala中的隐式转换

    所谓的隐式转换函数(implicit conversion function)指的是以implicit关键字申明的带有单个参数的函数,这样的函数会被自动的应用,将值从一种类型转换为另一种类型

使用方式:
1.将方法或变量标记为implicit
2.将方法的参数列表标记为implicit
3.将类标记为implicit
 
Scala支持两种形式的隐式转换:
隐式值:用于给方法提供参数
隐式视图:把一种类型自动转换到另一种类型

 

隐式转换的发生时机:

1、调用某个函数,但是给函数传入的参数类型,与函数定义的签名不匹配。

2、使用某个类型对象,调用某个方法,而这个方法并不存在于该类型时。

3、使用某个类型对象,调用某个方法,虽然该类型有这个方法,但是给方法传入的参数类型与签名并不一致的时候。

七、scala中的伴生类和伴生对象是怎么一回事

    在scala中,单例对象与类同名时,该对象被称为该类的伴生对象,该类被称为该对象的伴生类。

    伴生类和伴生对象要处在同一个源文件中

    伴生对象和伴生类可以互相访问其私有成员,外部不可访问

    不与伴生类同名的对象称之为孤立对象

//定义一个类
class MyClass(number: Int, text: String) {

  private val classSecret = 42

  def x = MyClass.objectSecret + "?"  // MyClass.objectSecret->在类中可以访问伴生对象的方法,在类的外部则无法访问
}

//定义一个伴生对象
object MyClass { // 和类名称相同
  private val objectSecret = "42"

  def y(arg: MyClass) = arg.classSecret -1 // arg.classSecret -> 在伴生对象中可以访问类的常量
}

MyClass.objectSecret // 无法访问
MyClass.classSecret // 无法访问

new MyClass(-1, "random").objectSecret // 无法访问
new MyClass(-1, "random").classSecret // 无法访问

八、scala和java 的区别

    1、变量申明:

        scala:只需要申明是val或是var,具体的类型(比如String,Int,Double等等),由编译器自行推断

        java:  需要在变量前面先注明变量的类型

    2、返回值:

        scala:申明返回值是在后面,并且不需要return语句,非要用,也不是不可以

        java:  如果有返回值,需要return语句

    3、结束符

        scala:不需要使用分号作为结束符

        java:  每个语句结束后需要分号作为结束符

    4、循环

        scala:循环语句可以用于守卫

        java:  不可以这么写

    5、通配符:

        scala:_

        java:   *

    6、构造器

        scala:构造器名称为this,scala的辅助构造器之前需要有一个主构造器或者其他辅助构造器,并且scala的构造器参数可以直接放在类的后面

        java:  构造器名称需要与类名称一样

    7、内部类

        scala:scala实例化的内部类是不同的,可以使用类型投影,例如 Network#Person表示Network的Person类

        java:内部类从属于外部类

    8、接口

        scala:scala中接口称为特质(trait),特质中是可以写抽象方法,也可以写具体的方法体以及状态。且类是可以实现多个特质的。

            特质中未被实现的方法默认就是抽象的

            子类的实现或继承统一使用的事extends关键字,如果需要实现或继承多个使用with关键字

            特质中可以有构造器

           特质可以继承普通的类,并且这个类称为所有继承trait的父类

        java:  java中的接口(interface),接口中的方法只能是抽象方法,不可以写具体包含方法体的方法

           接口中不能有抽象的属性,且属性的修饰符都是public static final

           类实现接口需要使用implements关键字,实现多个接口,需要用逗号隔开

             接口中不可以有构造器

             接口不可以继承普通的类 

    9、赋值

        scala:scala中的赋值语句返回结果是unit的不可以串联,例如x=y=1,这样是有问题的,x并没有被赋值为1

        java:  x=y=1,这样是没问题的

九、谈谈scala的尾递归

    正常递归,每一次递归步骤,需要保存信息到堆栈中去,当递归步骤很多的时候,就会导致内存溢出

    而尾递归,就是为了解决上述的问题,在尾递归中所有的计算都是在递归之前调用,编译器可以利用这个属性避免堆栈错误,尾递归的调用可以使信息不插入堆栈,从而优化尾递归

    例如:

1
2
3
4
5
6
7

正常递归:def sum(n:Int):Int = {
    if (n == 0){
      n
    }else{
      n + sum(n - 1)
    }
  }//执行结果sum(5)

5 + sum(4) // 暂停计算 => 需要添加信息到堆栈
5 + (4 + sum(3))
5 + (4 + (3 + sum(2)))
5 + (4 + (3 + (2 + sum(1))))
5 + (4 + (3 + (2 + 1)))
15

1
2
3
4
5
6
7
8
9

尾递归
@tailrec  //告诉编译器,强制使用尾递归
  def tailSum(n:Int,acc:Int = 0):Int = {
    if (n ==0 ){
      acc
    }else{
      tailSum(n - 1,acc + n)
    }
  }//执行结果tailSum(5) // tailSum(5, 0) 默认值是0

tailSum(4, 5) // 不需要暂停计算

tailSum(3, 9)

tailSum(2, 12)

tailSum(1, 14)

tailSum(0, 15)

15


十、var,val和def三个关键字之间的区别?

答:var是变量声明关键字,类似于Java中的变量,变量值可以更改,但是变量类型不能更改。
val常量声明关键字。
def 关键字用于创建方法(注意方法和函数的区别
还有一个lazy val(惰性val)声明,意思是当需要计算时才使用,避免重复计算

var x = 3 //  x是Int类型
x = 4      // 
x = "error" // 类型变化,编译器报错'error: type mismatch'

val y = 3
y = 4        //常量值不可更改,报错 'error: reassignment to val'

def fun(name: String) = "Hey! My name is: " + name
fun("Scala") // "Hey! My name is: Scala"

//注意scala中函数式编程一切都是表达式

scala> lazy val x = {
| println("computing x")
| 3
| }
x: Int = <lazy>

scala> val y = {
| println("computing y")
| 10
| }
computing y
y: Int = 10

scala> x+x
computing x
res4: Int = 6

scala> y+y
res5: Int = 20

scala> y
res6: Int = 10

十一、Scala中apply方法与unapply方法的使用

apply方法

通常,在一个类的伴生对象中定义apply方法,在生成这个类的对象时,就省去了new关键字。

unapply方法

可以认为unapply方法是apply方法的反向操作,apply方法接受构造参数变成对象,而unapply方法接受一个对象,从中提取值。

样例

class Currency(val value: Double, val unit: String) {

}

 

object Currency{

def apply(value: Double, unit: String): Currency = new Currency(value, unit)

def unapply(currency: Currency): Option[(Double, String)] = {

if (currency == null){

None

}

else{

Some(currency.value, currency.unit)

}

}

}


在构建对象的时候就可以直接使用val currency = Currency(30.2, "EUR")这种方式,不用使用new。
而unapply方法一般用于模式匹配


  1. def main(args: Array[String]): Unit = {

  2.  

  3. val currency = Currency(30.2, "EUR")

  4.  

  5. currency match {

  6. case Currency(amount, "USD") => println("$" + amount)

  7. case _ => println("No match.")

  8. }

  9. }


这段代码的输出为No match.如果将第二行改为val currency = Currency(30.2, "USD")那么输出为$30.2

 

十二、Scala类型系统中Nil, Null, None, Nothing四个类型的区别?

Null是一个trait(特质),是所以引用类型AnyRef的一个子类型,null是Null唯一的实例。
Nothing也是一个trait(特质),是所有类型Any(包括值类型和引用类型)的子类型,它不在有子类型,它也没有实例,实际上为了一个方法抛出异常,通常会设置一个默认返回类型。
Nil代表一个List空类型,等同List[Nothing]
None是Option monad的空标识

Unit代表没有任何意义的值类型,类似于java中的void类型,他是anyval的子类型,仅有一个实例对象"( )"

Option类型的定义和使用场景?

在Java中,null是一个关键字,不是一个对象,当开发者希望返回一个空对象时,却返回了一个关键字,

为了解决这个问题,Scala建议开发者返回值是空值时,使用Option类型,在Scala中null是Null的唯一对象,会引起异常,Option则可以避免。Option有两个子类型,Some和None(空值)

val person: Person = getPersonByIdOnDatabaseUnsafe(id = 4) // 如果没有id=4的person时,返回null对象
println(s"This person age is ${person.age}") //如果是null,抛出异常

val personOpt: Option[Person] = 
getPersonByIdOnDatabaseSafe(id = 4) // 如果没有id=4的person时,返回None类型

personOpt match {
  case Some(p) => println(s"This person age is ${p.age}")
  case None => println("There is no person with that id")
}

 

十三、call-by-value和call-by-name求值策略的区别?

(1)call-by-value是在调用函数之前计算;

(2)call-by-name是在需要时计算

/声明第一个函数
def func(): Int = {
  println("computing stuff....")
  42 // return something
}
//声明第二个函数,scala默认的求值就是call-by-value
def callByValue(x: Int) = {
  println("1st x: " + x)
  println("2nd x: " + x)
}
//声明第三个函数,用=>表示call-by-name求值
def callByName(x: => Int) = {
  println("1st x: " + x)
  println("2nd x: " + x)
}

//开始调用

//call-by-value求值
callByValue(func())   
//输出结果
//computing stuff....  
//1st x: 42  
//2nd x: 42

//call-by-name求值
callByName(func())   
//输出结果
//computing stuff....  
//1st x: 42  
//computing stuff....
//2nd x: 42

 

十四、yield如何工作?

yield用于循环迭代中生成新值,yield是comprehensions的一部分,是多个操作(foreach, map, flatMap, filter or withFilter)的composition语法糖。

// <-表示循环遍历
scala> for (i <- 1 to 5) yield i * 2 
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

comprehension(推导式)的语法糖是什么操作?

comprehension(推导式)是若干个操作组成的替代语法。如果不用yield关键字,comprehension(推导式)可以被forech操作替代,或者被map/flatMap,filter代替。

//三层循环嵌套
for {
  x <- c1
  y <- c2
  z <- c3 if z > 0
} yield {...}

//上面的可转换为
c1.flatMap(x => c2.flatMap(y => c3.withFilter(z => z > 0).map(z => {...})))

 

十五、Option ,Try 和 Either 三者的区别?、

这三种monads允许我们显示函数没有按预期执行的计算结果。
Option表示可选值,它的返回类型是Some(代表返回有效数据)或None(代表返回空值)。
Try类似于Java中的try/catch,如果计算成功,返回Success的实例,如果抛出异常,返回Failure。
Either可以提供一些计算失败的信息,Either有两种可能返回类型:预期/正确/成功的 和 错误的信息。

分享到:
评论

相关推荐

    Scala编程实战.zip

    此文档是讲解实战Scala,希望对喜欢大数据的同学有所帮助!!! 学习Scala语言,不仅仅意味着熟悉新的API,更重要的是一种思维方式的转变。从原有的面向对象编程(OO)到函数式编程(FP)的思想。本书面向实际的使用场景...

    Scala函数式编程

    很大篇幅都放在,使用scala实现scala默认库文件的API中,通过对简单的函数式编程逻辑的介绍和实践,主要是实践,建立起来一个比较明晰的scala思维模式,或者叫函数式编程的思维模式。 2 无副作用的函数式编程,同时...

    scala-parser-combinators-2.11-1.0.4-API文档-中文版.zip

    赠送jar包:scala-parser-combinators_2.11-1.0.4.jar; 赠送原API文档:scala-parser-combinators_2.11-1.0.4-javadoc.jar; 赠送源代码:scala-parser-combinators_2.11-1.0.4-sources.jar; 赠送Maven依赖信息...

    scala-xml_2.11-1.0.4-API文档-中英对照版.zip

    赠送jar包:scala-xml_2.11-1.0.4.jar; 赠送原API文档:scala-xml_2.11-1.0.4-javadoc.jar; 赠送源代码:scala-xml_2.11-1.0.4-sources.jar; 赠送Maven依赖信息文件:scala-xml_2.11-1.0.4.pom; 包含翻译后的API...

    scala-compiler-2.11.8-API文档-中英对照版.zip

    赠送jar包:scala-compiler-2.11.8.jar; 赠送原API文档:scala-compiler-2.11.8-javadoc.jar; 赠送源代码:scala-compiler-2.11.8-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.11.8.pom; 包含翻译后...

    scala-xml_2.12-1.0.6-API文档-中文版.zip

    赠送jar包:scala-xml_2.12-1.0.6.jar; 赠送原API文档:scala-xml_2.12-1.0.6-javadoc.jar; 赠送源代码:scala-xml_2.12-1.0.6-sources.jar; 赠送Maven依赖信息文件:scala-xml_2.12-1.0.6.pom; 包含翻译后的API...

    scala编程中文pdf

    scala编程 33章 中文pdf Scala编程实战 目录 第1章字符串. 11 第2章数值39 第3章控制结构.60 第4章类和属性.103 第5章方法147 第6章对象170 第7章包和导入.190 第8章特质200 第9章函数式编程214 第10 章集合242 第...

    scala-parser-combinators_2.11-1.0.4-API文档-中英对照版.zip

    赠送jar包:scala-parser-combinators_2.11-1.0.4.jar; 赠送原API文档:scala-parser-combinators_2.11-1.0.4-javadoc.jar; 赠送源代码:scala-parser-combinators_2.11-1.0.4-sources.jar; 包含翻译后的API...

    scala-java8-compat_2.11-0.7.0-API文档-中文版.zip

    赠送jar包:scala-java8-compat_2.11-0.7.0.jar; 赠送原API文档:scala-java8-compat_2.11-0.7.0-javadoc.jar; 赠送源代码:scala-java8-compat_2.11-0.7.0-sources.jar; 赠送Maven依赖信息文件:scala-java8-...

    flink-scala_2.12-1.14.3-API文档-中文版.zip

    赠送jar包:flink-scala_2.12-1.14.3.jar 赠送原API文档:flink-scala_2.12-1.14.3-javadoc.jar 赠送源代码:flink-scala_2.12-1.14.3-sources.jar 包含翻译后的API文档:flink-scala_2.12-1.14.3-javadoc-API...

    scala-sbt-scala编译工具

    scala 编译工具 sbt 安装包。 Little or no configuration required for simple projects Scala-based build definition that can use the full flexibility of Scala code Accurate incremental recompilation ...

    flink-scala-2.11-1.10.0-API文档-中文版.zip

    赠送jar包:flink-scala_2.11-1.10.0.jar; 赠送原API文档:flink-scala_2.11-1.10.0-javadoc.jar; 赠送源代码:flink-scala_2.11-1.10.0-sources.jar; 赠送Maven依赖信息文件:flink-scala_2.11-1.10.0.pom; ...

    scala五本经典资料集合

    scala是一个经典的语言,Scala代表了一个新的语言品种,它抹平了这些人为划分的界限。但是现在scala的相关学习资料不多,因此,本人总结了几篇写的较好的scala学习资料,包含&lt;ScalaQuery_Commerzbank_2011&gt;&lt;twitter-...

    Scala函数式编程.pdf

    Scala是一种能很好支持函数式编程的新兴JVM语言。《Scala函数式编程》是针对希望学习FP并将它应用于日常编码中的程序员而写的,内容包括:函数式编程的概念;函数式编程相关的各种“为什么”和“怎么做”;如何编写...

    scala 3本书打包

    这个打包文件中包含了《SCALA程序设计-JAVA虚拟机多核编程实战》《Scala编程-中文-完整版》《Scala in Action》三本书,足以让你从scala入门到精通,让我们一起愉快的学习吧。spark,scala醉了醉了。哈哈

    flink-1.14.4-scala_2.12 + CDH6.2.1 版 parcel 包

    flink-1.14.4-scala_2.12 + CDH6.2.1 版 parcel 包, 包含 FLINK-1.14.4-BIN-SCALA_2.12-el7.parcel FLINK-1.14.4-BIN-SCALA_2.12-el7.parcel.sha manifest.json (以上三个文件放入 /opt/cloudera/parcel-repo/ 下...

    SCALA编程思想 原书第2版 PDF 下载

    本书介绍Scala的基础特性,采用短小精悍的“原子”解构Scala语言的元素和方法。一个“原子”即为一个小型知识点,通过代码示例引导读者逐步领悟Scala的要义,结合练习鼓励读者在实践中读懂并写出地道的Scala代码。...

    scala-compiler-2.12.7-API文档-中文版.zip

    赠送jar包:scala-compiler-2.12.7.jar; 赠送原API文档:scala-compiler-2.12.7-javadoc.jar; 赠送源代码:scala-compiler-2.12.7-sources.jar; 赠送Maven依赖信息文件:scala-compiler-2.12.7.pom; 包含翻译后...

    差分进化算法的Scala实现_Scala_代码_下载

    差分进化算法的Scala实现_Scala_代码_下载

Global site tag (gtag.js) - Google Analytics