Scala 一文搞定

Posted 在奋斗的大道

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala 一文搞定相关的知识,希望对你有一定的参考价值。

第一节:概述

为什么学习Scala ?

Apache Spark 是专为大规模数据快速实时处理的计算引擎/内存级大数据计算框架。Apache Spark 是由Scala 语言编写。

Scala 与Java 关系

总结三点:

  • java 编译器与Scala 编译器可以相互使用。

  • Java SDK 的类库可以被Scala使用,Scala支持对Java 类库进行封装。Java 无法访问Scala特有类库

  • Scala 支持Java语法,JDK不支持Scala 特有语法。

Scala 语言特性

Scala 环境搭建

请参考文章:Windows 安装Scala 详情

IDEA 安装Scala 插件

默认情况下IDEA不支持Scala的开发,需要安装Scala插件。

我这里选择离线安装Scala 插件

a. IDEA的Scala插件地址: https://plugins.jetbrains.com/plugin/1347-scala/versions,找到自己的IDEA版本所对应的版本下载。

知识拓展:如何查看IDEA 是否支持Scala插件

b. 下载后是一个压缩包,将插件放于Scala安装目录下的plugin目录下

c. IDEA进入Settings,选择Plugins,选择从磁盘安装,然后选择Scala插件压缩包即可。

Scala 之Hello World

创建IDEA项目工程

1)打开IDEA->点击左侧的Flie->选择New->选择Project…

2)在src包下,创建包com.zzg.chapt01名和Hello类名,

右键点击src目录->New->Package->输入com.zzg.chapt01->点击OK。

右键点击com.zzg.chapt01->New->Scala Class->Kind项选择Object->Name项输入Hello

编写输出Hello Scala案例

在类中中输入main,然后回车可以快速生成main方法;

在main方法中输入println(“Hello World Scala”)

package com.zzg.chapt01

object Hello 
  def main(args: Array[String]): Unit = 
    println("Hello World Scala");
  

控制台结果输出:

Hello World 程序详细说明

//main 方法名、程序入口
//小括号表示参数列表
//  Java 与scala 参数声明方式: java  ->  类型  参数名
//                           scala ->  参数名 : 类型
//  public修饰符:  scala中没有public关键字,如果不声明访问权限,那么就是公共的
//  static修饰符:  scala中没有静态方法,所以没有static关键字
//  void关键字:  表示返回值,但是不遵守面向对象语法,所以scala中没有,但是又Unit类型,表示没有返回值
//  scala中: 方法名(参数列表):返回值类型
//  scala中方法必须采用关键字def声明
//  scala中方法实现赋值给方法声明,所以中间需要等号连接

//  scala是一个完全面向对象的语言,所以没有静态语法,为了能调用静态语法(模仿静态语法)
//  采用伴生对象单例的方式调用方法


/*
* Scala 完全面向对象,故scala去掉了Java中非面向对象的元素,如static关键字,void类型
* 1) static
*     scala无static关键字,由object实现类似静态方法的功能(类名.方法名)
*     class关键字和Java中的class关键字作用相同,用来定义一个类
* 2) void
*     对于无返回值的函数,scala定义其返回值类型为Unit类型
*
* */
package com.zzg.chapt01

object Hello 
  def main(args: Array[String]): Unit = 
    println("Hello World Scala");
  

第二节:Scala 变量和支持数据类型

2.1 注释

Scala 注释与Java 注释完全一样。

基本语法:

(1)单行注释://

(2)多行注释:/* */

(3)文档注释:/**
            *
            */

知识拓展:编码规范

(1)使用一次tab操作,实现缩进,默认整体向右边移动,用shift+tab整体向左移

(2)或者使用ctrl + alt + L来进行格式化

(3)运算符两边习惯性各加一个空格。比如:2 + 4 * 5

(4)一行最长不超过80个字符,超过的请使用换行展示,尽量保持格式优雅

2.2 变量和常量(重点

Java 变量和常量语法声明:

​ 变量类型 变量名称 = 初始值 
 eg:int a = 1

​ final 常量类型 常量名称 = 初始值 
 eg: final int b = 2

Scala 变量和常量语法声明:

 var 变量名 [: 变量类型] = 初始值 
 eg:var i:Int = 10

​ val 常量名 [: 常量类型] = 初始值 
 eg:val j:Int = 20

知识拓展:能用常量就不要使用变量。

Scala 实例:

(1)声明变量时,类型可以省略,编译器自动推导,即类型推导

(2)类型确定后,就不能修改,说明Scala是强数据类型语言。

(3)变量声明时,必须要有初始值

(4)在声明/定义一个变量时,可以使用var或者val来修饰,var修饰变量可改变,val修饰常量不可改。

package com.zzg.chapt02

object VariableAndConstantDemo 
  def main(args: Array[String]): Unit = 
    // 定义Int 类型变量
    var a:Int = 10;
    // 类型推导
    var b = 10;


    // 定义Double 类型变量
    var c:Double = 3.1415;
    // 变量类型确定,不允许修改, 编译直接提示错误
    // var d:Int = c;

    // 定义变量, 不赋值, 编译器直接提示 错误
    // var e;

    // 定义常量
    val  f:Int = 10;
    // 修改常量, 编译器直接提示错误
    // f = 11;
  

(5)var修饰的对象引用可以改变,val修饰的对象则不可改变,但对象的状态(值)却是可以改变的。(比如:自定义对象、数组、集合等等)

package com.zzg.chapt02

/**
 * 复杂对象
 */
object ComplexObjectDemo 
  def main(args: Array[String]): Unit = 
      // a对象使用var变量声明, 对象属性可以修改,对象状态也可以修改
      var a = new Person();
      // 对象属性修改
      a.name = "Jane";
      // 对象状态修改
      a = null;

      // b 对象使用val 常量声明,对象属性可以修改,对象状态不可以修改
      val b = new Person();
      // 对象属性修改
      b.name = "Tom";
      // 对象状态修改, 编译器直接提示错误。
      // b = null;
  

  /**
   * 内部类定义
   */
  class Person 
    var name = "Jack";
  



2.3 标识符命名规范

Scala 命名规范与Java 命名规范一致

(1)以字母或者下划线开头,后接字母、数字、下划线

(2)以操作符开头,且只包含操作符(+ - * / # !等)

(3)用反引号....包括的任意字符串,即使是Scala关键字(39个)也可以

• package, import, class, object, trait, extends, with, type, for

• private, protected, abstract, sealed, final, implicit, lazy, override

• try, catch, finally, throw

• if, else, match, case, do, while, for, return, yield

• def, val, var

• this, super

• new

• true, false, null

2.4 字符串输出

基本语法:

(1)字符串,通过+号连接

(2)printf用法:字符串,通过%传值。

(3)字符串模板(插值字符串):通过$获取变量值

package com.zzg.chapt02

object StringInputDemo 
  def main(args: Array[String]): Unit = 
    var str1:String = "Hello ";
    var str2:String = "Scala"
    // 字符串输出:使用 +号 连接
    println(str1 + str2)

    // 字符串输出: 使用%号传值
    printf("my name is =%s", str2);

    /**
     *  多行字符串输出:
     *  1、 在Scala中,利用三个双引号包围多行字符串就可以实现。
     *  2、 问题:输入的内容,带有空格、\\t之类,导致每一行的开始位置不能整洁对齐。
     *  3、 解决办法:使用Scala中stripMargin, 默认是“|”作为连接符, 要求:多行字符串的每一行的行头前面加一个“|”符号, 实现格式化
     */
    val sql =
      """
      |select
      |name
      |from
      |base_user
      |where
      |id = 1
    """.stripMargin

    println(sql);


    var id:Int =1;
    // 字符串输出: 使用$号传值
    val formateSql =
      s"""
        |select
        |name
        |from
        |base_user
        |where
        |id = $id
    """.stripMargin

    println(formateSql);
  

2.5 键盘输入

基本语法:

  1. StdIn.readLine() : 读取行记录

  1. StdIn.readShort():读取Short

  1. StdIn.readDouble(): 读取Double

package com.zzg.chapt02

import scala.io.StdIn

object KeyWordInouDemo 
  def main(args: Array[String]): Unit = 
    //    输入姓名
    println("input name:")
    var name = StdIn.readLine()

    //    输入年龄
    println("input age:")
    var age = StdIn.readShort()

    printf("my name is =%s", name);
    println();
    printf("my age is =%d", age);



  

2.6 数据类型

Java 数据类型

Java基本数据类型:char、byte、short、int、long、float、double、boolean
Java引用类型:(对象类型)
由于Java有基本类型,而且基本类型不是真正意义的对象,即使后面产生了基本类型的包装类,但是仍然存在基本数据类型,所以Java语言并不是真正意义上的面向对象
Java基本类型的包装类:Character、Byte、Short、Integer、Long、Float、Double、Boolean
温馨提示:Java中基本类型和引用类型没有共同的祖先。

Scala 数据类型

2.7 整数类型

整数分类

数据类型

描述

Byte [1]

8位有符号补码整数。数值区间为 -128 到 127

Short [2]

16位有符号补码整数。数值区间为 -32768 到 32767

Int [4]

32位有符号补码整数。数值区间为 -2147483648 到 2147483647

Long [8]

64位有符号补码整数。数值区间为 -9223372036854775808 到 9223372036854775807 = 2的(64-1)次方-1

Scala 实例:

(1)Scala各整数类型有固定的表示范围和字段长度,不受具体操作的影响,以保证Scala程序的可移植性。

(2)Scala的整型,默认为Int型,声明Long型,须后加‘l’或‘L’

package com.zzg.chapt02

object DataTypeDemo 
  def main(args: Array[String]): Unit = 
    // Scala各整数类型有固定的表示范围和字段长度
    // 正确
    var a: Byte = 127
    var b: Byte = -128

    // 错误
    //    var c:Byte = 128
    //    var d:Byte = -129


    // Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
    var e = 10
    println(e)

    var f = 98989898989898989L
    println(f)

  

2.8 浮点类型

浮点型分类

数据类型

描述

Float [4]

32 位, IEEE 754标准的单精度浮点数

Double [8]

64 位 IEEE 754标准的双精度浮点数

Scala 实例:

(1)Scala的浮点型常量默认为Double型,声明Float型常量,须后加‘f’或‘F’。

package com.zzg.chapt02

object DataTypeDemo 
  def main(args: Array[String]): Unit = 
    // Scala各整数类型有固定的表示范围和字段长度
    // 正确
    var a: Byte = 127
    var b: Byte = -128

    // 错误
    //    var c:Byte = 128
    //    var d:Byte = -129


    // Scala的整型,默认为Int型,声明Long型,然后加”i“ 或者 ”L“
    var e = 10
    println(e)

    var f = 98989898989898989L
    println(f)

    //Scala 声明Float类型,须后加‘f’或‘F’。
    var g =1283732f
    println(g)

  

2.9 字符类型

基本说明:

字符类型可以表示单个字符,字符类型是Char。

Scala 实例:

(1)字符常量是用单引号 ’ ’ 括起来的单个字符。

(2)\\t :一个制表位,实现对齐的功能

(3)\\n :换行符

(4)\\ :表示\\

(5)" :表示"

package com.zzg.chapt02

object CharTypeDemo 
  def main(args: Array[String]): Unit = 
    // 字符定义使用''括起来
    var a:Char = 'a';
    println(a);

    //注意:这里涉及自动类型提升,其实编译器可以自定判断是否超出范围
    // var b:Char = 'a' + 1

    //    \\t :一个制表位,实现对齐的功能
    println("姓名\\t年龄")

    //   \\n :换行符
    println("西门庆\\n潘金莲")

    //(4)\\\\ :表示\\
    println("c:\\\\天黑了\\\\饿狼来了")

    //(5)\\" :表示"
    println("你过来:\\"看我一拳打死你\\"")

  

控制台输出:

D:\\Java\\jdk1.8.0_121\\bin\\java.exe -Dvisualvm.id=756107015780000 "-javaagent:D:\\Program Files\\JetBrains\\IntelliJ IDEA Community Edition 2022.1\\lib\\idea_rt.jar=52353:D:\\Program Files\\JetBrains\\IntelliJ IDEA Community Edition 2022.1\\bin" -Dfile.encoding=UTF-8 -classpath D:\\java\\jdk1.8.0_121\\jre\\lib\\charsets.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\deploy.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\access-bridge-64.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\cldrdata.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\dnsns.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\jaccess.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\jfxrt.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\localedata.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\nashorn.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunec.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunjce_provider.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunmscapi.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\sunpkcs11.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\ext\\zipfs.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\javaws.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jce.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jfr.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jfxswt.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\jsse.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\management-agent.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\plugin.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\resources.jar;D:\\java\\jdk1.8.0_121\\jre\\lib\\rt.jar;E:\\scala_workspace\\ScalaDemo\\out\\production\\ScalaDemo;D:\\scala\\lib\\scala-library.jar;D:\\scala\\lib\\scala-reflect.jar com.zzg.chapt02.CharTypeDemo
a
姓名    年龄
西门庆
潘金莲
c:\\天黑了\\饿狼来了
你过来:"看我一拳打死你"

2.10 布尔类型

基本说明:

(1)布尔类型也叫Boolean类型,Booolean类型数据只允许取值true和false

(2)boolean类型占1个字节。

Scala 实例:

package com.zzg.chapt02

class BooleanTypeDemo 
  def main(args: Array[String]): Unit = 
    var isTrue:Boolean =true;
    var isFalse:Boolean = false;
  

2.11 Unit类型、Null类型和Nothing类型(重点)

基本说明:

Scala 实例:

(1)、Unit 修饰没有返回值函数。

(2)、Null类只有一个实例对象,Null类似于Java中的null引用。Null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)

(3)、Nothing,可以作为没有正常返回值的方法的返回类型,非常直观的告诉你这个方法不会正常返回,而且由于Nothing是其他任意类型的子类,他还能跟要求返回值的方法兼容。

package com.zzg.chapt02

object NullAndNullAndNothingDemo 
  def main(args: Array[String]): Unit = 
    // 调用Unit 函数
    println(num)

    // null可以赋值给任意引用类型(AnyRef),但是不能赋值给值类型(AnyVal)
    var person = new Person()
    person = null

    //var a: Int = null // IDEA编译错误:an expression of type Null is ineligible for implicit conversion
    //println("a is:" + a)

    // 调用过期函数, 抛出异常信息。
    calculate();
  

  /**
   * 定义Unit 函数
   */
  def num:Unit =
    println("Unit 函数被调用")
  

  /**
   * 定义引用类型(AnyRef)
   */
  class Person

  

  /**
   * 定义calculate函数,会抛出异常
   * @return
   */
  def calculate():Nothing=
    throw new Exception;
  

2.12 类型转换

当Scala程序在进行赋值或者运算时,精度小的类型自动转换为精度大的数值类型,这个就是自动类型转换(隐式转换)。数据类型按精度(容量)大小排序为:

基本说明

(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数据类型,然后再进行计算。

(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。

(3)(byte,short)和char之间不会相互自动转换。

(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。

Scala 实例:

package com.zzg.chapt02

object ValueTransDemo 
  def main(args: Array[String]): Unit = 
    //(1)自动提升原则:有多种类型的数据混合运算时,系统首先自动将所有数据转换成精度大的那种数值类型,然后再进行计算。
    var a = 1 + 2.2222
    println(a) //Double

    //(2)把精度大的数值类型赋值给精度小的数值类型时,就会报错,反之就会进行自动类型转换。
    var b: Double = 2.2222
    //    var c: Int = b //报错

    //(3)(byte,short)和char之间不会相互自动转换。
    var d: Byte = 44
    //    var e : Char = d//报错
    var f: Int = d

    //(4)byte,short,char他们三者可以计算,在计算时首先转换为int类型。
    var g: Byte = 66
    var h: Char = 22
    //    var l : Short = g + b  //报错,结果是Int类型
    //    var m : Short = 10 + 20  //报错,byte,short,char他们三者可以计算,在计算时首先转换为int类型。

  

强制类型转换

基本说明:

自动类型转换的逆过程,将精度大的数值类型转换为精度小的数值类型。使用时要加上强制转函数,但可能造成精度降低或溢出,格外要注意。

语法说明:

Java : int num = (int)2.1
Scala : var num : Int = 2.1.toInt

Scala 实例:

(1)将数据由高精度转换为低精度,就需要使用到强制转换

(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级

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

//(1)将数据由高精度转换为低精度,就需要使用到强制转换
var n1: Int = 2.5.toInt // 这个存在精度损失

//(2)强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级
var r1: Int = 10 * 3.5.toInt + 6 * 1.5.toInt // 10 *3 + 6*1 = 36
var r2: Int = (10 * 3.5 + 6 * 1.5).toInt // 44.0.toInt = 44

println("r1=" + r1 + " r2=" + r2)

数值类型和String类型间转换

基本说明:

在程序开发中,我们经常需要将基本数值类型转成String类型。或者将String类型转成基本数值类型。

Scala 实例:

(1)基本类型转String类型(语法:将基本类型的值+“” 即可)

(2)String类型转基本数值类型(语法:s1.toInt、s1.toFloat、s1.toDouble、s1.toByte、s1.toLong、s1.toShort)

def main(args: Array[String]): Unit = 
    //(1)基本类型转String类型(语法:将基本类型的值+"" 即可)
    var str1: String = true + "你kin"
    println(str1)
    var str2: String = 4.444 + "拜拜"
    println(str2)
    var str3: String = 4444 + ""
    println(str3)

    //(2)String类型转基本数值类型(语法:调用相关API)
    var s1: String = "11"
    var n1: Byte = s1.toByte
    var n2: Short = s1.toShort
    var n3: Int = s1.toInt
    var n4: Long = s1.toLong
    println(s1)
    println(n1)
    println(n2)
    println(n3)
    println(n4)

第三节: Scala 运算符

Scala运算符的使用和Java运算符的使用基本相同,只有个别细节上不同。

算术运算符

(1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。小数之间做除法时,保留整数和小数部分

(2)对一个数取模a%b,和Java的取模规则一样。

Scala 实例:

package com.zzg.chapt02

object ArithmeticDemo 
  def main(args: Array[String]): Unit = 
    //    1)对于除号“/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃小数部分。
    var a: Int = 10 / 3
    println(a) //3

    var b: Double = 10 / 3
    println(b) //3.0

    var c: Double = 10.0 / 3
    println(c) //3.3333333333333335
    println(c.formatted("%.2f")) //3.33  含义:保留小数点2位,使用四舍五入

    //(2)对一个数取模a%b,和Java的取模规则一样。
    var d = 10 % 3
    println(d) //1

  

关系运算符(比较运算符)

Scala 实例:

package com.zzg.chapt02

object RelationDemo 
  def main(args: Array[String]): Unit = 
    var a:Int = 1
    var b:Int = 2

    println(a > b) // false
    println(a >= b) // false
    println(a < b) // true
    println(a <= b) // true
    println(a == b) // false
    println(a != b) // true

  

知识拓展:Java和Scala中关于==的区别

Java:==比较两个对象在内存地址;equals比较两个对象toString生成内容是否相同。

Scala: == 等价于Java 的equals 方法。

逻辑运算符

Scala 实例:

package com.zzg.chapt02

object LogicDemo

  def main(args: Array[String]): Unit = 
    var a: Boolean = true;
    var b: Boolean = false;

    println(a && b) // false
    println(a || b) // true
    println(!a || !b) // true
  

赋值运算符

温馨提示:Scala中没有++、– –操作符,可以通过+=、-=来实现同样的效果;

Scala 实例:

package com.zzg.chapt02

object AssignmentDemo 
  def main(args: Array[String]): Unit = 
    var a:Int =10;

    a += 1 // 11
    println(a);

    a -= 1 // 10
    println(a);
  

位运算符

表中变量 a 为 60,b 为 13

Scala运算符本质

在Scala中其实是没有运算符的,所有运算符都是方法。

1)当调用对象的方法时,点.可以省略

2)如果函数参数只有一个,或者没有参数,()可以省略

package com.zzg.chapt02

object OperateDemo 
  def main(args: Array[String]): Unit = 
    // 标准的加法运算
    val i:Int = 1.+(1)

    // (1)当调用对象的方法时,.可以省略
    val j:Int = 1 + (1)

    // (2)如果函数参数只有一个,或者没有参数,()可以省略
    val k:Int = 1 + 1

    println(1.toString())
    println(1.toString)

  

第四节: Scala 流程控制

if语句

if单分支语句

基本语法:

if (条件表达式)
执行代码块

温馨提示:当条件表达式为ture时,就会执行 的代码。

if 双分支语句

基本语法:

if (条件表达式)
执行代码块1
else
执行代码块2

温馨提示:当条件表达式为true 时,执行代码块1,否则执行代码块2。

if 多分支语句

基本语法:

if (条件表达式1)
执行代码块1

else if (条件表达式2)
执行代码块2

……
else
执行代码块n

温馨提示:有满足结果为true的条件表达式,就执行条件表达式代码,否则执行else 代码。

Scala 实例:

package com.zzg.chapt02

import scala.io.StdIn

object IfExpressionDemo 
  def main(args: Array[String]): Unit = 
    println("input age:")
    var age: Int =  StdIn.readInt();

    if(age <= 18) 
      println("儿童")
     else if(age > 18 && age <= 45)
      println("青年")
     else if(age > 45 && age <= 60)
      println("中年");
     else
      println("老年")
    
  

嵌套分支

在一个分支结构中又完整的嵌套了另一个完整的分支结构,里面的分支的结构称为内层。分支外面的分支结构称为外层分支。温馨提示:嵌套分支不要超过3层

基本语法:

if()
    if()
        
    else
    
    

Scala 实例:针对年龄类判断,优化调整:对于小于等于18条件,在细分:小于等于6 为儿童,其他为少年。

package com.zzg.chapt02

import scala.io.StdIn

object IfExpressionDemo 
  def main(args: Array[String]): Unit = 
    println("input age:")
    var age: Int =  StdIn.readInt();

    if(age <= 18) 
      if(age <= 6)
        println("儿童")
       else 
        println("少年")
      
     else if(age > 18 && age <= 45)
      println("青年")
     else if(age > 45 && age <= 60)
      println("中年");
     else
      println("老年")
    
  

Switch分支结构

在Scala中没有Switch语句,而是使用模式匹配来处理。

此章节在模式匹配/正则表达式再详细讲解。

For循环控制/For 推导式/For 表达式

Scala 为For 循环控制这一常见的控制结构提供了非常多的特性。

范围数据循环(To)

基本语法:

for(i <- start to end)
println(i + " ")

说明:

(1)i 表示循环的变量,初始值start

(2)i 将会从 start-end 循环,前后闭合/[]

范围数据循环(Until)

基本语法:

for(i <- start until end)
println(i + " ")

说明:

(1)这种方式和前面的区别在于i是从start到start - end

(2)即使前闭合后开的范围/[)

循环守卫

基本语法:

for(i <- start to end if condition)
println(i + " ")

说明:

(1)循环守卫,即循环保护式(也称条件判断式,守卫)。保护式为true则进入循环体内部,为false则跳过,类似于continue。

对等代码

for(i <- start to endd)
if(condition)
println(i + " ")

循环步长

基本语法:

for (i <- start to end by step)
println(“i=” + i)

嵌套循环

基本语法:

for(i <- start to end; j <- start to end)
println(" i =" + i + " j = " + j)

说明:没有关键字,所以范围后一定要加;来隔断逻辑

引入变量

基本语法

for(i <- start to end; j = parameter - i)

println("i=" + i + " j=" + j)

说明:

(1)for推导式一行中有多个表达式时,所以要加 ; 来隔断逻辑

(2)for推导式有一个不成文的约定:当for推导式仅包含单一表达式时使用圆括号,当包含多个表达式时,一般每行一个表达式,并用花括号代替圆括号,如下

Scala 实例

package com.zzg.chapt03

object ForVariableDemo 
  def main(args: Array[String]): Unit = 
    // For 引入变量, 形式一
    for(i <- 1 to 3; j= 5 -i)
      println("i =" + i + ", j =" + j);
    
    println("----------------------------")
    // For 引入变量, 形式二
    for
      i <- 1 to 3
      j = 5 -i
    
      println("i =" + i + ", j =" + j);
    
  

循环返回值

基本语法:

val result = for(i <- start to end) yield i

说明: 将遍历过程中处理的结果返回到一个新Vector集合中,使用yield关键字。

温馨提示:在开发中使用场景较少。

倒序打印

基本语法:

for(i <- start to end reverse)
println(“i=” + i)

说明:倒序打印一组数据,可以使用reverse

While和do…While循环控制

While和do…While的使用和Java语言中用法相同。

While循环控制

基本语法:

循环变量初始化

while (循环条件) 

   循环体(语句)

   循环变量迭代

说明:

(1)循环条件是返回一个布尔值的表达式

(2)while循环是先判断再执行语句

(3)与for语句不同,while语句没有返回值,即整个while语句的结果是Unit类型()

(4)因为while中没有返回值,所以当要用该语句来计算并返回结果时,就不可避免的使用变量,而变量需要声明在while循环的外部,那么就等同于循环的内部对外部的变量造成了影响,所以不推荐使用,而是推荐使用for循环。

Scala 实例

package com.zzg.chapt03

object WhileDemo 
  def main(args: Array[String]): Unit = 
    var a: Int = 10;
    while (a > 1) 
      println("a =" + a)
      a -=1
    
  

do…while循环控制

基本语法:

循环变量初始化;
do
循环体(语句)
循环变量迭代
while(循环条件)

说明:

(1)循环条件是返回一个布尔值的表达式

(2)do…while循环是先执行,再判断

Scala 实例

package com.zzg.chapt03

object DoWhileDemo 
  def main(args: Array[String]): Unit = 
    var a:Int = 0;
    do
      println("a =" + a);
      a += 1
    while(a < 10)
  

循环中断

Scala内置控制结构特地去掉了break和continue,是为了更好的适应函数式编程.

Scala 推荐使用Breaks.break()控制结构来实现break和continue功能。

Scala 实例:采取异常方式,跳出for 循环

package com.zzg.chapt03

object ForExceptionDemo 
  def main(args: Array[String]): Unit = 
    try 
      for (i <- 1 to 10) 
        println("i = " + i);
        if (i == 8) 
          throw new RuntimeException()
        
      
      println("for 循环正常结束")
    catch
      case e =>
        println("for 循环通过异常结束")
    
  

Scala 实例:通过Scala 自带函数(Breaks.break()),退出for循环

package com.zzg.chapt03

import scala.Console.println
import scala.util.control.Breaks

object BreaksDemo 
  def main(args: Array[String]): Unit = 
    Breaks.breakable(
      for (i <- 1 to 10) 
        println("i = " + i);
        if (i == 8) 
          println("通过Breaks中止for 循环")
          Breaks.break()
        
      
    )
    println("for 循环正常中止")
  

第五节:Scala 函数式编程

面向对象编程、函数式编程区别

1)面向对象编程

解决问题,分解对象,行为,属性,然后通过对象的关系以及行为的调用来解决问题。

对象:用户

行为:登录、连接JDBC、读取数据库

属性:用户名、密码

Scala语言是一个完全面向对象编程语言。万物皆对象

对象的本质:对数据和行为的一个封装

2)函数式编程

解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用这些封装好的步骤,解决问题。

例如:请求->用户名、密码->连接JDBC->读取数据库

Scala语言是一个完全函数式编程语言。万物皆函数。

函数的本质:函数可以当做一个值进行传递

3)在Scala中函数式编程和面向对象编程完美融合在一起了。

函数

基本语法:

Scala 实例

package com.zzg.chapt04

object FunctionDemo 
  def main(args: Array[String]): Unit = 
    /**
     * 自定义sum 函数
     * @param x
     * @param y
     * @return
     */
    def sum(x:Int, y:Int):Int =
        x + y
    
    // 调用sum 函数
    println("sum is =" + sum(1, 2))


  

函数和方法的区别

核心概念

(1)为完成某一功能的程序语句的集合,称为函数。

(2)类中的函数称之方法。

Scala 实例

(1)Scala语言可以在任何的语法结构中声明任何的语法

(2)函数没有重载和重写的概念;方法可以进行重载和重写

(3)Scala中函数可以嵌套定义

package com.zzg.chapt04

object Function01Demo 
  //  2.方法可以进行重载和重写,程序可以执行
  def main(): Unit = 
    println("main 方法重新")
  

  def main(args: Array[String]): Unit = 
    //  1.Scala语言可以在任何的语法结构中声明任何的语法
    import java.util.Date
    new Date()

    //  3.函数没有重载和重写的概念,程序报错
    def test(): Unit = 
      println("无参,无返回值")
    

    test()

//    def test(): Unit = 
//      println()
//    

//    4.Scala 中函数可以嵌套定义
    def test2() :Unit = 
      def test3(name:String):Unit=
        println("函数可以嵌套定义")
      
      test3("函数嵌套")
    
    test2()
  

函数定义

1)函数定义

(1)函数1:无参,无返回值

(2)函数2:无参,有返回值

(3)函数3:有参,无返回值

(4)函数4:有参,有返回值

(5)函数5:多参,无返回值

(6)函数6:多参,有返回值

Scala 实例

package com.zzg.chapt04

object FunctionDefinitionDemo 
  def main(args: Array[String]): Unit = 
    // 无参函数, 调用函数省略()
    this.one;
    this.two();
    this.three("Scala");
    this.four("Scala");
    this.five(1, 2);
    this.six(1, 2);

  

  /**
   * 函数1:无参,无返回值
   */
  def one :Unit =
    println("无参,无返回值")
  

  /**
   * 函数2:无参,有返回值
   */
  def two() :Int =
    println("无参,有返回值")
    return 1
  

  /**
   * 函数3:有参,无返回值
   */
  def three(x:String) :Unit =
    println("x =" + x)
    println("有参,无返回值")
  

  /**
   * 函数4:有参,有返回值
   * @return
   */
  def four(x:String) :String =
    println("x =" + x)
    return x;
  

  /**
   * 函数5:多参,无返回值
   * @param a
   * @param b
   */
  def five(a: Int, b:Int) : Unit =
    println("a =" + a +", b=" + b)
  

  /**
   * 函数6:多参,有返回值
   * @param a
   * @param b
   * @return
   */
  def six(a:Int, b:Int) : Int =
    println("a =" + a +", b=" + b)
    return a + b
  

函数参数

1)参数说明

(1)可变参数

(2)如果参数列表中存在多个参数,那么可变参数一般放置在最后

(3)参数默认值,一般将有默认值的参数放置在参数列表的后面

(4)带名参数

package com.zzg.chapt04

object FunctionParamterDemo 
  def main(args: Array[String]): Unit = 
    this.one("Hello", "Scala")
    this.two("Hi", "Scala", "!")
    // 如果参数有默认值,在调用的时候,可以省略这个参数
    this.three("zzx");
    // 如果参数传递了值,那么会覆盖默认值
    this.three("zzy", 12);
    // 默认调用不传递参数名称
    this.four("zzh");
    // 调用传递参数名称
    this.four(name="zty");


  

  /**
   * 函数:可变参数
   * @param parame
   */
  def one(parameters:String*):Unit=
    println(parameters)
  

  /**
   * 函数:参数列表中存在多个参数,那么可变参数一般放置在最后
   * @param name
   * @param paramters
   */
  def two(name:String, paramters:String*):Unit=
    println("name =" + name);
    println(paramters)
  

  /**
   * 函数:参数默认值
   * @param name
   * @param age
   */
  def three(name:String, age:Int = 18):Unit=
    println(s"$name = $age")
  

  /**
   * 函数:参数携带参数名称传递
   * @param name
   */
  def four(name:String):Unit=
    println("name =" + name)
  

函数至简原则(重点)

函数至简原则:能省则省

1)至简原则细节

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

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

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

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

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

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

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

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

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

Scala 实例

待补充。

函数高级

在Scala中,函数是一等公民。

Scala 实例

package com.zzg.chapt04

object FunctionAdvancedDemo 
  def main(args: Array[String]): Unit = 
    this.one()
  

  /**
   * Scala 函数是第一公民
   */
  def one():Unit=
    println("函数未声明, 直接调用")
  

函数高级用法

函数值传递

(1)、函数赋值给变量

(2)、被调用函数后面加上 _, 相当于把函数当成一个整体,再赋值给变量

(3)、明确变量类型,不适用下划线也可以将函数作为整体传递给变量

Scala 实例

package com.zzg.chapt04

object FunctionAdvancedDemo 
  def main(args: Array[String]): Unit = 
    this.one()
    // 函数赋值给变量 方式一
    var func = this.two();
    println(func)
    // 变量直接赋值
    var b = func;
    println(b)

    // 函数赋值给变量 方式二
    var c = this.two _; // 等价于拷贝two 函数源码
    println(c) //  输出函数地址引用
    println(c()) // 整体调用函数

    // 函数赋值给变量 方式三
    var d : () => Int = two // 通过匿名函数, 接受函数返回值,再赋值给变量。
    println(d())
  

  /**
   * Scala 函数是第一公民
   */
  def one():Unit=
    println("函数未声明, 直接调用")
  

  /**
   * Scala 函数赋值给变量
   * @return
   */
  def two():Int =
    return 1
  

函数参数传递

package com.zzg.chapt04

object Function02Demo 
  def main(args: Array[String]): Unit = 
    // (1)定义一个函数,函数参数还是一个函数签名,f表示函数名称;(Int,Int)表示输入两个Int参数;Int表示函数返回值
    def complexF(f:(Int,Int) =>Int) :Int=
      return this.add(2, 4)
    
   // (3) 将add函数作为参数传递给complexF函数,如果能够推断出来不是调用,_可以省略
    println(complexF(add));
    println(complexF(add _))
  
  //    (2) 定义一个函数,参数和返回值类型和complexF的输入参数一致
  def add(a:Int, b:Int):Int=
    return a + b;
  

函数作为返回值返回

package com.zzg.chapt04

/**
 * 函数作为返回值返回
 */
object Function03Demo 
  def main(args: Array[String]): Unit = 
    def a() =
      def b() =
        println("函数嵌套")
        println("-------------------")
      
      // 函数b后面加上 _, 相当于把函数b当成一个整体。
      b _
    

    var c = a();
    println(c) // 打印函数整体的内存地址
    println("---------------")
    println(c()) // 执行函数
  

匿名函数

基本说明:

没有名字的函数就是匿名函数。

基本语法:

(x:Int)=>函数体

温馨提示:x:表示输入参数类型;Int:表示输入参数类型;函数体:表示具体代码逻辑。

Scala 实例

​ 功能需求:传递的函数有一个参数

传递匿名函数至简原则:

(1)参数的类型可以省略,会根据形参进行自动的推导

(2)类型省略之后,发现只有一个参数,则圆括号可以省略;其他情况:没有参数和参数超过1的永远不能省略圆括号。

(3)匿名函数如果只有一行,则大括号

以上是关于Scala 一文搞定的主要内容,如果未能解决你的问题,请参考以下文章

Spark SQL functions.scala 源码解析String functions (基于 Spark 3.3.0)

Spark SQL functions.scala 源码解析Aggregate functions(基于 Spark 3.3.0)

PySpark源码解析,教你用Python调用高效Scala接口,搞定大规模数据分析

Spark 中用 Scala 和 java 开发有啥区别

学习Scala 进击大数据Spark生态圈

Scala和Spark的大数据分析