Scala学习笔记:重要知识点摘记

一、Scala基础语法

  1. Scala 中使用 val 语句可以定义函数,def 语句定义方法。

  2. Scala是面向行的语言, 语句末尾的分号 ; 是可选的。

  3. Scala没有java中的原生类型

  4. Scala用'''xxx''' 表示多行字符串

  5. 如果没有指定访问修饰符,默认情况下,Scala 对象的访问级别都是 public

  6. Scala 中的 private 限定符,比 Java 更严格,在嵌套类情况下,外层类甚至不能访问被嵌套类的私有成员。

  7. scala 中,对保护(Protected)成员的访问比 java 更严格一些。因为它只允许保护成员在定义了该成员的的类的子类中被访问。而在java中,用protected关键字修饰的成员,除了定义了该成员的类的子类可以访问,同一个包里的其他类也可以进行访问。

  8. Scala中,访问修饰符可以通过使用限定词强调。格式为:

          private[x] protected[x]

  9. private[x],读作"这个成员除了对[…]中的类或[…]中的包中的类及它们的伴生对像可见外,对其它所有类都是private

  10. Scala 程序使用 Option 非常频繁,在 Java 中使用 null 来表示空值,代码中很多地方都要添加 null 关键字检测,不然很容易出现 NullPointException。因此 Java 程序需要关心那些变量可能是 null,而这些变量出现 null 的可能性很低,但一但出现,很难查出为什么出现 NullPointerException

11. Scala 代码中"$"作用:在String 中直接拼接 字符串 和数字 等类型 = >  简化了字符串拼接(注意格式:s"" ,最前面有个s)    

name = "haven"
age = 12
println(s"name=$name,age=${age+1}")

${}内可嵌入任何表达式  :

println(s"name=$name,age=${age+1}")

 

 

Scala Option 类型可以避免这种情况,因此 Scala 应用推荐使用 Option 类型来代表一些可选值。使用 Option 类型,读者一眼就可以看出这种类型的值可能为 None

二、private作用域

 

private[this] :只有本对象中可见

private[spark] class Hello表示什么含义

表示这个类只能在包名中含有spark的类中访问

 

三、import

 

import org.apache.spark.SparkContext._         引用SparkContext类里面的所有成员

import org.apache.spark._          引用org.apache.spark包下的所有类

import org.apache.spark.{SparkConf, SparkContext}        引用 同一个包下的多个类,可以写到一起

import org.apache.spark.{SparkContext=>SC}

表示在使用SparkContext的地方,可以使用它的别名SC,比如SparkContext sc可以写成SC sc

 

如果想要引入包中的几个成员,可以使用selector(选取器):

import java.awt.{Color, Font}

// 重命名成员

import java.util.{HashMap => JavaHashMap}

// 隐藏成员

import java.util.{HashMap => _, _} // 引入了util包的所有成员,但是HashMap被隐藏了

 

四、for

 // 查找数组中的最大元素
      var max = myList(0);
      for ( i <- 1 to (myList.length - 1) ) {
         if (myList(i) > max) max = myList(i);
      }

五、Object伴生类

 

1. scala没有静态的修饰符,为了弥补,引入object伴生类。object伴生类下的成员都是静态的 ;

2.当object修饰对象与某个class修饰的类有相同的名称时,该对象为这个类的伴生类(companion object);

3. 在object中一般可以为伴生类做一些初始化等操作,(mian函数也是在Object伴生类中使用);

4. 类和它的伴生对象可以互相访问其私有成员。

5. object对象不能带参数;

6. 必须在同一个源文件里定义类和它的伴生对象;

7. 单例模式实现方法时,使用Object关键字:

8.伴生对象实例:

// 私有构造方法
class Marker private(val color:String) {

  println("创建" + this)
  
  override def toString(): String = "颜色标记:"+ color
  
}

// 伴生对象,与类名字相同,可以访问类的私有属性和方法
object Marker{
  
    private val markers: Map[String, Marker] = Map(
      "red" -> new Marker("red"),
      "blue" -> new Marker("blue"),
      "green" -> new Marker("green")
    )
    
    def apply(color:String) = {
      if(markers.contains(color)) markers(color) else null
    }
  
    
    def getMarker(color:String) = { 
      if(markers.contains(color)) markers(color) else null
    }
    def main(args: Array[String]) { 
        println(Marker("red"))  
        // 单例函数调用,省略了.(点)符号  
        println(Marker getMarker "blue")  
    }
}

六、定义了二维数组的实例:

var myMatrix = ofDim[Int](3,3)

 

七、Scala 数组方法

下表中为 Scala 语言中处理数组的重要方法,使用它前我们需要使用 import Array._ 引入包。

序号

方法和描述

1

def apply( x: T, xs: T* ): Array[T]

创建指定对象 T 的数组, T 的值可以是 Unit, Double, Float, Long, Int, Char, Short, Byte, Boolean

2

def concat[T]( xss: Array[T]* ): Array[T]

合并数组

3

def copy( src: AnyRef, srcPos: Int, dest: AnyRef, destPos: Int, length: Int ): Unit

复制一个数组到另一个数组上。相等于 Java's System.arraycopy(src, srcPos, dest, destPos, length)

4

def empty[T]: Array[T]

返回长度为 0 的数组

5

def iterate[T]( start: T, len: Int )( f: (T) => T ): Array[T]

返回指定长度数组,每个数组元素为指定函数的返回值。

以上实例数组初始值为 0,长度为 3,计算函数为a=>a+1

scala> Array.iterate(0,3)(a=>a+1)

res1: Array[Int] = Array(0, 1, 2)

6

def fill[T]( n: Int )(elem: => T): Array[T]

返回数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。

7

def fill[T]( n1: Int, n2: Int )( elem: => T ): Array[Array[T]]

返回二数组,长度为第一个参数指定,同时每个元素使用第二个参数进行填充。

8

def ofDim[T]( n1: Int ): Array[T]

创建指定长度的数组

9

def ofDim[T]( n1: Int, n2: Int ): Array[Array[T]]

创建二维数组

10

def ofDim[T]( n1: Int, n2: Int, n3: Int ): Array[Array[Array[T]]]

创建三维数组

11

def range( start: Int, end: Int, step: Int ): Array[Int]

创建指定区间内的数组,step 为每个元素间的步长

12

def range( start: Int, end: Int ): Array[Int]

创建指定区间内的数组

13

def tabulate[T]( n: Int )(f: (Int)=> T): Array[T]

返回指定长度数组,每个数组元素为指定函数的返回值,默认从 0 开始。

以上实例返回 3 个元素:

scala> Array.tabulate(3)(a => a + 5)

res0: Array[Int] = Array(5, 6, 7)

14

def tabulate[T]( n1: Int, n2: Int )( f: (Int, Int ) => T): Array[Array[T]]

返回指定长度的二维数组,每个数组元素为指定函数的返回值,默认从 0 开始。

 

八、Scala 继承

Scala继承一个基类(父类)跟Java很相似, 但我们需要注意以下几点:

1重写一个非抽象方法必须使用override修饰符。

class Person {

    var name = ""

    override def toString = getClass.getName + "[name=" + name + "]"

}

2、只有主构造函数才可以往基类的构造函数里写参数。

3、在子类中重写超类的抽象方法时,你不需要使用override关键字。

九、Scala之Implicit的用法

9.1基本描述

Scala在面对编译出现类型错误时,提供了一个由编译器自我修复的机制。编译器试图去寻找一个隐式implicit的转换方法,转换出正确的类型,完成编译。这就是implicit 的意义。

1.将方法或变量标记为implicit
2.
将方法的参数列表标记为implicit
3.
将类标记为implicit

Scala支持两种形式的隐式转换:
隐式值:用于给方法提供参数
隐式视图:用于类型间转换或使针对某类型的方法能调用成功

【注意点】

       隐式转换必须满足无歧义规则,在声明隐式参数的类型是最好使用特别的或自定义的数据类型,不要使用Int,String这些常用类型,避免碰巧匹配

9.2 转换时机

1.当方法中的参数的类型与目标类型不一致时
2.当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换

 

9.3 解析机制

即编译器是如何查找到缺失信息的,解析具有以下两种规则:

1.首先会在当前代码作用域下查找隐式实体(隐式方法  隐式类 隐式对象)

2.如果第一条规则查找隐式实体失败,会继续在隐式参数的类型的作用域里查找

类型的作用域是指与该类型相关联的全部伴生模块,一个隐式实体的类型T它的查找范围如下:

    1)如果T被定义为T with A with B with C,那么A,B,C都是T的部分,在T的隐式解析过程中,它们的伴生对象都会被搜索

    2)如果T是参数化类型,那么类型参数和与类型参数相关联的部分都算作T的部分,比如List[String]的隐式搜索会搜索List

伴生对象和String的伴生对象

    3 如果T是一个单例类型p.T,即T是属于某个p对象内,那么这个p对象也会被搜索

    4 如果T是个类型注入S#T,那么ST都会被搜索

9.4 转换前提

1.不存在二义性(如例1

2. 隐式操作不能嵌套使用,即一次编译只隐式转换一次(One-at-a-time Rule)

Scala不会把 x + y 转换成 convert1(convert2(x)) + y

3.代码能够在不使用隐式转换的前提下能编译通过,就不会进行隐式转换。

https://www.cnblogs.com/xia520pi/p/8745923.html

十、Scala Trait(特征)

 

1. Scala Trait(特征)相当于 Java 的接口,实际上它比接口还功能强大。

2. 与接口不同的是,它还可以定义属性和方法的实现

3. 一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。

4. Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait,如下所示:

trait Equal {

  def isEqual(x: Any): Boolean

  def isNotEqual(x: Any): Boolean = !isEqual(x)

}

十一、Case模式匹配

“_”为默认选项

def matchTest(x: Int): String = x match {

      case 1 => "one"

      case 2 => "two"

      case _ => "many"

   }

 

十二、Scala 提取器(Extractor)

 

1. apply方法无需new操作就可以创建对象,而unapply方法则用于析构出对象;

(在模式匹配中特别提到,如果一个类要能够应用于模式匹配当中,必须将类声明为case class,因为一旦被定义为case class,Scala会自动帮我们生成相应的方法,这些方法中就包括apply方法及unapply方法。)

代码示例:

object EMail{

  //apply方法用于无new构造对象

  def apply(user: String, domain: String) = user + "@" + domain



 //unapply方法用于在模式匹配中充当extractor

 def unapply(str: String): Option[(String, String)] = {

 val parts = str split "@"

 if (parts.length == 2) Some(parts(0), parts(1)) else None

 }

 }

 object ApplyAndUnapply {

   val email=EMail("zhouzhihubeyond","sina.com")

   //下面的匹配会导致调用EMail.unapply(email)

   case EMail(user,domain) => println("user="+user+" domain="+domain)

 }

 }

2. Scala 提取器是一个带有unapply方法的对象。unapply方法算是apply方法的反向操作:unapply接受一个对象,然后从对象中提取值,提取的值通常是用来构造该对象的值。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值