View on GitHub

个人笔记

SongPinru 的小仓库

入门

计算机语言发展历史

  • 机器语言
  • 汇编语言
  • 高级语言
    • 编译型语言:C、C++ &如果需要多次运行程序,不需要对源文件进行多次编译 &不支持跨平台
  • 解释型语言 :JavaScript &支持跨平台 &如果需要多次运行程序,需要对源文件进行多次解释

Java运行原理

先编译后解释 .java源文件–>编译器–>.class字节码文件–>windowsJVM(解释) –>LinuxJvm ……

Scala运行原理

先编译后解释 .scala源文件–>编译器–>.class字节码文件–>windowsJVM(解释) –>LinuxJvm ……

JDK安装以及环境变量的配置

  • path 告诉操作系统,去什么位置找相关的执行文件

  • JAVA_HOME 规避对系统级别环境变量造成误修改的风险 随着Java的不断流行,JAVA_HOME配置成了一个标准,有些软件要求必须配置该变量

Scala第一个案例

object Hello_Scala{
    def main(args:Array[String]):Unit={
        println("Hello_Scala")
    }
}    
  • Scala语言,没有Java中的static关键字。通过伴生对象实现类似的效果
  • 伴生对象声明的语法 object + 名字
  • 底层会自动帮我编译生成两个字节码文件,一个是伴生类,另外一个是伴生对象所属类,其实真正的伴生对象指的是伴生对象所属类中的一个单例对象。
  • 在Scala语言中,要想实现static的效果,需要在伴生对象中定义

基础语法

Scala中注释

  • 单行注释 //
  • 多行注释 /**/
  • 文档注释 /** */

    Scala中下划线使用

  • 标识符命名
  • 在匿名函数中,如果参数在函数体中只使用一次,可以使用下划线代替
  • 导包
    • 导入包下的所有类
    • 导入类下的所有成员
    • 屏蔽类
  • 函数作为值进行传递 函数名 _
  • 声明属性的时候,给属性赋默认值
  • 模式匹配 case _

变量和常量

  • 语法 var|val 名称:数据类型 = 值
  • var 值可以改变

  • val 只能被赋值一次

标识符命名规则

字符串输出

  • 使用 + 进行拼接
  • printf %d %s %f
  • ”"”字符串””” 让字符串保持格式输出
  • 通过${}获取变量,字符串前面用小s标记

获取用户键盘输入

  • StdIn
  • readLine
  • readInt

数据类型

  • Any是Scala中最顶层的父类
    • AnyVal值类型
    • AnyRef引用类型
  • 几个比较特殊的类型
    • Unit 表示返回值为空 ,相当于Java中的void 只有一个实例 ()
    • Null 表示的引用类型变量没有指向堆中对象
      只有一个实例 null 只能赋给引用类型,不能赋值给值类型
    • Nothing 表示方法没有正常的时候,用Nothing来标记 一般是发生异常了

程序的流程控制

顺序流程

分支流程(选择)

单分支

双分支

多分支

Scala的分支有返回值,每个分支体中最后一行代码,如果多个分支体中返回的数据类型不一致,会找共同祖先类型作为返回值。 -循环流程

范围数据循环 start to end start until end
for(循环变量<-集合 数组)

在Scala中,没有break和continue关键字

continue

可以在循环体中进行条件判读 循环守卫

  • break(循环中断)

    通过抛出异常的方式,中断循环 通过Scala提供的Breaks(breakable、break)方法,中断循环, 底层也是通过抛出异常的方式实现的 可以导入Breaks类中的所有成员,类似java中静态导入 import xxxx.xxxx.Breaks._

  • 循环步长
    • 针对的是范围类型数据
    • by
  • 循环引入变量

  • 循环嵌套

函数式编程

函数的基本用法

Java 访问控制修饰符 返回值类型 函数名(参数列表)异常{ 函数体 }

Scala def 函数名(参数名:参数类型):返回值类型={ 函数体 } 参数类型: Int\String\函数 (参数)=>返回值类型

函数的参数

可变长参数

参数名:参数类型*

一个参数列表中,至多只能有一个可变长参数

可变长参数应该出现在参数列表的最后

参数的默认值

定义形参的时候可以指定默认值

如果形参有默认值,那么在调用函数的是时候,参数可以不传

带名参数

函数至简原则

(1)return可以省略,Scala会使用函数体的最后一行代码作为返回值

(2)如果函数体只有一行代码,可以省略花括号

(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)

(4)如果有return,则不能省略返回值类型,必须指定

(5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用

(6)Scala如果期望是无返回值类型,可以省略等号

(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加

(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略

(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略

数据类型

Int,String,函数 (参数类型)=>返回值类型,代码块 =>返回值类型

匿名函数 : 没有名字的函数

(1)参数的类型可以省略,会根据形参进行自动的推导 (2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。 (3)匿名函数如果只有一行,则大括号也可以省略 (4)如果参数只出现一次,则参数省略且后面参数可以用_代替

高阶函数

  • 函数的更高级的用法
  • 在Scala中,函数是一等公民
  • 函数可以作为值进行传递
  • 函数可以作为参数进行传递
  • 函数可以作为返回值进行传递
//函数可以作为值进行传递
    def f1():Int={10}
    //var f = f1
    //var f = f1 _
    var f:()=>Int = f1
    f()
//函数可以作为返回值进行传递    
    def f1():()=>Unit{
        var a:Int = 10
        def f2(){
            a
        }
        f2 _
    }
    f1()()

闭包

内层函数访问外层函数的局部变量,会自动延长外层函数的局部变量的生命周期,与内层函数形成一个闭合的效果,我们称之为闭包 闭包 = 外层函数的局部变量 + 内层函数

柯里化

  • 前提:有闭包
  • 简化函数的嵌套编写,将一个参数列表的多个参数,拆分为多个参数列表
    def f(外层函数参数)(内层函数参数){
        内层函数处理
    }

控制抽象

  • 值调用 传递的是函数执行完毕之后的数值

  • 名调用 传递的是代码块

  • 惰性函数

    scala

类和对象

  • 对象 只要是客观存在的事物都是对象
    • 对大量对象共性的抽象

      有什么 属性 能做什么 方法

    • 是创建对象的模板
    • 是客观事物在人脑中的主观反应

Scala中的包

  • 声明包的方式
    • java一样的声明方式
    • 嵌套的声明方式

      一个源文件中可以定义多个package

      子包的类可以直接使用父包中的类 ,而不需要进行导包

Scala中的封装

  • 在Scala中,属性和方法默认是公开的,但是Scala中没有public关键字
  • 如果是公开的属性,底层会自动对属性进行封装,生成私有属性,提供公开的设置以及获取属性值的方法。
  • 为了支持某些框架,要想提供get set方法,需要在属性上加@BeanProperty

构造方法

  • 主构造方法 *在声明类的同时,也声明了主构造方法
  • 辅助构造方法 *方法名必须叫this *第一行代码,必须直接或者间接调用主构造方法 *辅助构造方法可以重载
  • 存在继承关系,在创建子类对象的时候,需要递归的构造父类对象

抽象类、抽象属性、抽象方法

  • 在Scala中,属性和方法都可以是抽象的
  • 抽象属性 只有属性的声明,没有赋值
  • 抽象方法 只有方法的声明,没有方法的实现
  • 在一个类中,如果存在抽象属性或者抽象方法,那么这个类一定是抽象类 -如果一个类是抽象类,那么不一定存在抽象属性或者抽象方法
  • 如果一个类是抽象类,抽象属性以及抽象方法应该交给子类实现 -如果子类也实现不了,那么子类也应该定义为抽象的

Scala创建对象的两种方式

  • new 类名()
    底层调用的是构造方法

  • 类名() 底层调用的是伴生对象的apply的方法

  • 单例设计模式

特质

  • 在Scala中,用特质替代Java中接口的概念
  • 使用trait关键声明,在特质中可以声明抽象属性、非抽象属性、抽象方法以及非抽象方法
  • 让一个类具有某一个特质,我们称之为混入特质
    • 如果当前类没有继承父类, 类 extends 特质A with 特质B….
    • 如果当前类继承父类, 类 extends 父类 with 特质A with 特质B….
  • 特质冲突(特质叠加) MyOperation extends HDFSOperation with DBOperation

    • 列出混入的第一个特质的继承关系,作为临时叠加顺序 HDFSOperation–>Operation

    • 列出混入的第二个特质的继承关系,并放到临时叠加顺序的前面,已经出现的特质不再重复 DBOperation –> HDFSOperation–>Operation

    • 将子类放到临时叠加顺序的第一个位置,得到最终的顺序 MyOperation–>DBOperation –> HDFSOperation–>Operation

  • super不是表示其父特质对象,而是表示上述叠加顺序中的下一个特质

集合中常用的方法

  • 获取集合长度 length
  • 获取集合大小 size
  • 循环遍历 foreach
  • 迭代器 iterator
  • 生成字符串 mkString
  • 是否包含 contains
  • 获取集合的头 head
  • 获取集合的尾(不是头的就是尾) tail
  • 集合最后一个数据 last
  • 集合初始数据(不包含最后一个) init
  • 反转 reverse
  • 取前(后)n个元素 take|takeRight
  • 去掉前(后)n个元素 drop|dropRight
  • 并集 union
  • 交集 intersect
  • 差集 diff
  • 拉链 zip
  • 滑窗 sliding
  • 求和 sum
  • 求乘积 produce
  • 最大值 max
  • 最小值 min
  • 排序 sorted sortby sortWith
  • 过滤 filter
  • 转化/映射 map
  • 扁平化 flatten
  • 扁平化+映射 flatMap
  • 分组 groupBy
  • 简化(归约) reduce|reduceLeft|reduceRight
  • 折叠 fold|foldLeft|foldRight