`
flylynne
  • 浏览: 376821 次
  • 性别: 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 sdk scala-2.12.3

    Scala SDK,全称为Scala Software Development Kit,是用于开发Scala应用程序的核心工具集。Scala是一种多范式的编程语言,融合了面向对象和函数式编程的特点,它运行在Java虚拟机(JVM)上,能够充分利用Java生态...

    Scala-2.11.1.zip

    Scala是一种强大的静态类型编程语言,它融合了面向对象和函数式编程的概念,旨在提供一种可扩展的、高效的编程环境。Scala这个名字是“Scalable Language”的缩写,它旨在克服Java的一些局限性,同时保留其平台兼容...

    scala3 scala3 scala3 scala3 scala3

    Scala3,也被称为Scala 3或Dotty,是Scala编程语言的一个重大更新,旨在提高其简洁性、可读性和类型安全性。Scala3的发布标志着该语言的进一步成熟,它引入了一系列改进,旨在解决早期版本中的一些痛点,同时保持对...

    scala2.12.1Windows镜像包

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念。这个"scala2.12.1Windows镜像包"是为Windows操作系统设计的Scala编程环境的安装包,版本号为2.12.1。Scala 2.12.x系列是其重要的一个稳定...

    scala学习源代码

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。这个"scala学习源代码"的压缩包文件很可能包含了用于教学或自我学习Scala编程的基础示例。让我们深入了解一下Scala语言的关键概念和特性。 ...

    scala-2.12.10.zip

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念。这个"scala-2.12.10.zip"文件是Scala编程语言的特定版本——2.12.10,专为Windows操作系统设计的安装包。Scala 2.12.x系列是该语言的一个...

    scala + mybatis 数据库查询

    Scala是一种强大的多范式编程语言,它结合了面向对象和函数式编程的特性。MyBatis则是一款流行的Java持久层框架,主要用于简化数据库操作。在本项目中,"scala + mybatis 数据库查询",我们将探讨如何将Scala与...

    Scala考试题1

    Scala 是一种多范式的编程语言,它融合了面向对象和函数式编程的特性。下面将详细解释题目中涉及的Scala知识点: 1. **var、val 和 def 的区别**: - `var` 定义可变变量,可以多次赋值。 - `val` 定义不可变变量...

    scala-2.12.10.tgz

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念。Scala运行在Java虚拟机(JVM)上,并且可以充分利用Java的生态系统。`scala-2.12.10.tgz`是一个针对Linux操作系统的Scala安装包,它的版本号...

    scala实战高清讲解

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,使得它在处理并发和大数据分析方面表现出色。"Scala实战高清讲解"这本书是学习Scala的宝贵资源,尤其对于那些希望深入理解并提升Scala技能的...

    scala-2.12.14.zip&scala-2.12.11.tgz Linux版本压缩包.rar

    Scala是一种强大的多范式编程语言,它融合了面向对象编程和函数式编程的概念,被广泛应用于大数据处理和分布式计算领域,特别是在Apache Spark等框架中。标题提到的"scala-2.12.14.zip&scala-2.12.11.tgz"是Scala的...

    scala-2.13.8 解压安装版

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。这个"scala-2.13.8 解压安装版"提供了一个无需安装过程的便捷方式来使用Scala开发环境。以下是关于Scala-2.13.8版本的一些关键知识点: 1. ...

    scala-2.12.6.tgz

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念,设计目标是提供一种静态类型系统,能够防止程序在运行时出现错误。Scala-2.12.6.tgz是一个针对该语言的最新版本安装包,用于在各种操作系统...

    Programming.in.Scala.pdf

    从上述内容来看,《Programming in Scala.pdf》不仅是一本介绍Scala编程语言的书籍,更是一本为读者提供深入了解和应用Scala语言的实用工具。书籍中的内容覆盖了从基础知识到高级特性的多个层面,确保读者能够在掌握...

    官网scala-2.11.8版本安装包

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特点,广泛应用于大数据处理、分布式计算和Web开发等领域。Spark是一个基于Scala构建的大数据处理框架,它以其高效、易用和可扩展性而受到业界的...

    scala-2.11.7 包

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。Scala-2.11.7是该语言的一个特定版本,适用于Java虚拟机(JVM)。这个包是官方发布的,确保了其可靠性和兼容性。 在安装Scala-2.11.7时,...

    学习scala好的项目

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理、分布式计算和Web开发等领域。Spark是基于Scala构建的大数据处理框架,其高性能和易用性使得Scala在大数据领域备受...

    最好的scala学习 课件

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性,被广泛应用于大数据处理领域,特别是与Apache Spark相结合时。本课件是针对Scala学习者精心准备的资源,旨在帮助你深入理解和掌握Scala的...

    windows版scala-2.11.12.zip

    在这个"windows版scala-2.11.12.zip"压缩包中,包含的是Scala 2.11.12版本的Windows兼容安装文件,这是Scala的一个稳定版本,适用于开发人员在Windows操作系统上进行Scala编程。 Scala 2.11.x系列是Scala的一个主要...

    scala-2.12.13.tgz

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的概念,为开发者提供了丰富的工具集。这个"scala-2.12.13.tgz"文件是Scala编程语言的一个版本,针对Linux操作系统提供的安装包。tgz(tar.gz)格式...

Global site tag (gtag.js) - Google Analytics