scala 返回值_Scala--基本语法

7b773f3b4f1ddc678121914da821dc46.png

一、变量和数据类型

注释

 // 单行注释
 ​
 /*
   多行注释
  */
 ​
 /**
   * doc注释
   */

变量

变量的定义:

 var | val 变量名 :变量类型 = 变量值
 var 可变类型
 var name :String = "zhangsan"
 val 不可变类型
 val sex :String = "mile"

注意:

  • 变量的类型如果能够通过变量值推断出来,那么可以省略类型声明
  • 变量必须进行显示初始化
  • 一般默认为val类型变量

字符串

在Scala 中的字符串的类型实际上就是 Java中的 String类,它本身是没有 String 类的。

 //字符串连接
 print("hello"+word)
 //传值字符串
 printf("name=%sn", name)
 //插值字符串
 println(s"name=$name")
 //多行字符串
 println(
            s"""
              | Hello
              | ${name}
   """.stripMargin('|'))

输入与输出

  • 从屏幕(控制台)中获取输入
 val str:String = scala.io.StdIn.readLine()
  • 从文件中获取输入
 scala.io.Source.fromFile("input/abc.txt").getLines()

输出:Scala进行文件写操作,用的都是 java中的I/O类

 val writer = new PrintWriter(new File("output/aaa.txt"))
 writer.write("Hello Scala")
 writer.close()

数据类型

Scala是完全面向对象的语言,所以不存在基本数据类型的概念,有的只是任意值对象类型(AnyVal)和任意引用对象类型(AnyRef)

58671a01f03a428b6907cbc243e143de.png

类型转换

自动类型转换(隐式转换

问:Scala中的类型之间没有继承关系怎么可以自动转换?

答:scala中的数值类在编译后对应java中的基本数据类型,所有可以进行自动转换

强制类型转化

 var a : Int = 10
 Var b : Byte = a.toByte
 // 基本上Scala的AnyVal类型之间都提供了相应转换的方法。

字符串类型转化

toString:scala是完全面向对象的语言,所有的类型都提供了toString方法,可以直接转换为字符串

运算符

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

  • scala是完全面向对象的语言,所以数字其实也是对象
  • 当调用对象的方法时,点.可以省略
  • 如果函数参数只有一个,或者没有参数,()可以省略

二、流程控制

分支控制

单分支

 if(布尔表达式) {
    // 如果布尔表达式为 true 则执行该语句块
 }

双分支

 if(布尔表达式) {
    // 如果布尔表达式为 true 则执行该语句块
 } else {
    // 如果布尔表达式为 false 则执行该语句块
 }

多分支

 if(布尔表达式1) {
    // 如果布尔表达式1为 true,则执行该语句块
 } else if ( 布尔表达式2 ) {
    // 如果布尔表达式2为 true,则执行该语句块
 }...
 } else {
    // 上面条件都不满足的场合,则执行该语句块
 }

注意:Scala中没有三元运算符,可以用双分支代替

循环控制

for循环

 for ( 循环变量 <- 数据集 ) {
     循环体
 }
 //数据集为集合,数组,字符串等类型

循环守卫

 for (i <- Range(1,5) if i != 3){
     println("i = "+i)
 }
 // if i != 3 即为循环守卫

循环步长

 for (i <- 1 to 5 by 2){
     println("i = "+ i)
 }
 // by 2 即为循环步长

循环嵌套

 for (i <- 1 until 5 ; j <- 1 until 5){
     println("i = " + i + ", j = " + j )
 }

引入变量

 for ( i <- Range(1,5); j = i - 1 ) {
             println("j = " + j )
         }

循环返回值

 val result = for ( i <- Range(1,5) ) yield {
             i * 2
         }
 //如果希望for循环表达式的返回值有具体的值,需要使用关键字yield

while循环

 while( 循环条件表达式 ) {
     循环体
 }
 and
 do {
     循环体
 } while ( 循环条件表达式 )

循环中断

 import scala.util.control.Breaks._
 breakable {
    for ( i <- 1 to 5 ) {
        if ( i == 3 ) {
           break
        }
    println(i)
    }
 }
 //scala中没有break关键字,用函数的方式代替了关键字

三、函数式编程

基础函数编程

基本语法

 [修饰符] def 函数名 ( 参数列表 ) [:返回值类型] = {
     函数体
 }
 private def test( s : String ) : Unit = {
     println(s)
 }

函数与方法的区别

在类中声明的函数即为方法,方法可以有重载和重写,而函数没有,但函数可以嵌套的使用而方法不能

函数的至简原则

 //函数的基至简原则
     def function(name:String):String={
       println("基本语法")
       return name
     }
     //(1)return可以省略,Scala会使用函数体的最后一行代码作为返回值
     def function1(name:String):String={
       println("省略return")
       name
     }
     //(2)如果函数体只有一行代码,可以省略花括号
     def function2 (name:String):String= name
     //(3)返回值类型如果能够推断出来,那么可以省略(:和返回值类型一起省略)
     def function3(name:String)=name
     //(4)如果有return,则不能省略返回值类型,必须指定
     def function4(name:String):String= return name
     //(5)如果函数明确声明unit,那么即使函数体中使用return关键字也不起作用
     def function5(name:String):Unit=return name
     //(6)Scala如果期望是无返回值类型,可以省略等号
     def function6(name:String) {println(name+"期望无返回值类型")}
     //(7)如果函数无参,但是声明了参数列表,那么调用时,小括号,可加可不加
     def function7() {println("无参调用")}
     function7
     //(8)如果函数没有参数列表,那么小括号可以省略,调用时小括号必须省略
     def function8 = println("定义时无()则必省")
     function8
     //(9)如果不关心名称,只关心逻辑处理,那么函数名(def)可以省略
     val fun9 = (name:String)=> {println(name+"省略函数名")
     }
     fun9("小明:")

高级函数编程

函数的调用

  //1.函数的调用
     def function(name:String):Unit={
       println(name+"函数基本调用")
     }
     function("小明")
     //1)函数可以作为值进行传递
     //后面加 _ 来调用
     val fun11 = function _
     fun11("小明")
     //指明函数类型来调用
     val fun12:String=>Unit=function
     fun12("小明")
     //2)函数可以作为参数进行传递
     def function12(f:(String)=>Unit):String={
       f("小明")
       "函数参数传递"
     }
     //如果能够推断出函数是传递而不是调用,则 _ 可以省略
     val str = function12(function _)
     val str1=function12(function)
     println(str)
     //3)函数可以作为函数返回值返回
     def function13(name1:String):String=>Unit={
       println(name1+"  外部函数")
       def fun13(name2:String):Unit={
         println(name2+"函数作为返回值")
       }
       //注意要看能否推断出返回值类型,如果返回值类型没有指定,则需用 fun3 _
       // fun13 _
       fun13
     }
     function13("小明")("小红")

匿名函数

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

闭包和函数柯里化

 //3.闭包
     //如果一个函数,访问到了它的外部(局部)变量的值,那么这个函数和他所处的环境,称为闭包
     def function3(a:Int)={
       def fun3(b:Int)= a+b
       fun3 _
     }
     println(function3(5)(5))
     //4.函数柯里化
     //把一个参数列表的多个参数,变成多个参数列表。
     def function4(a:Int)(b:Int)={
       println(a + b)
     }
     function4(5)(4)

递归

 //5.递归
     //scala中的递归必须声明函数返回值类型
     def function5(x:Int):Int={
       if (x<=1) 1
       else x * function5(x-1)
     }
     println(function5(6))
     //发散递归容易导致栈溢出,下面是改进
     def function51(x:Int,res:Int):Int={
       if (x<=1) res
       else function51(x-1,x*res)
     }
     println(function51(6,1))

控制抽象

 //6.控制抽象
     //1)值调用:把计算后的值传递过去
     def foo1(a:Int):Unit={
       println(a)
       println(a)
     }
     def function61=()=>{
       println("function61....")
       20
     }
     foo1(function61())
     //2)名调用:把代码传递过去
     def foo2(a:  =>Int):Unit={
       println(a)
       println(a)
     }
     def function62:()=>Int=()=>{
       println("function62----")
       40
     }
     foo2(function62())

惰性函数

     //7.惰性函数
     //当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。
     def function7(a:Int,b:Int)={
       println("函数定义")
       a+b
     }
     lazy val res = function7(5,6)
     println("执行一些代码")
 ​
     println("res = "+ res)

四、面向对象编程

基础面向对象编程

  • Scala中的包和类的物理路径没有关系
  • package关键字可以嵌套声明使用
  • 子包可以直接访问父包中的内容,而无需import
  • Scala中package也可以看作对象,并声明属性和函数

导入

  • Scala中使用下划线代替Java中的星号:import java.util._
  • Scala中的import语法可以在任意位置使用
  • Scala中可以导包,而不是导类:import java.util
  • Scala中可以在同一行中导入多个类,简化代码:import java.util.{List, ArrayList}
  • Scala中可以屏蔽某个包中的类:import java.sql.{ Date=>_ , Array=> _ , _ }
  • Scala中可以给类起别名,简化使用:import java.util.{ArrayList=>AList}
  • Scala中可以使用类的绝对路径而不是相对路径:import root.java.util.ArrayList
  • 默认情况下,Scala中会导入如下包和对象
 import java.lang._
 import scala._
 import scala.Predef._

伴生类和伴生对象?

class : 编译完后只生成一个class文件. xxx.class

object :编译完后生成两个class文件. xxx.class xxx$.class

Scala中没有static语法. 通过object来模仿java的static语法. 并且会有一个单例的对象(xxx$.class)

object修饰类,最终生成了两个字节码文件,我们把object修饰的类称之为伴生类. 把随着伴生类产生的单例对象称之为伴生对象.

后来,我们统一将class修饰的类就称之为伴生类, 把object修饰的类称之为伴生对象。

属性

JavaBean规范: 属性私有,提供公开的get/set方法.

Java中的属性:

   private String name ;
    public void setName(String name ){this.name = name }
    public String getName(){return this.name}

Scala中的属性: 使用默认的修饰符声明了属性, 编译后,属性是通过private修饰的, 并同时提供了该属性的公开的 "get" / "set" 方法.

如果属性声明的时候通过private修饰,编译后,属性也是通过private修饰的, 提供的"get" / "set" 方法也是private修饰的

属性如果通过val声明,必须直接初始化. 编译后,属性通过final修饰.

问题: 按照javaBean规范,属性需要私有化,提供公开的 get / set 方法, Scala怎么办?

很多框架底层会通过反射的方式操作属性的 get / set方法实现对属性值的修改和读取. ​ 如果在Scala中希望生成属性的get/set方法, 可以通过@BeanProperty来标注属性

访问权限

 Java 的访问权限:
    private    :   本类
    [default]  :   本类   本包
    protected  :   本类   本包   子类
    public     :   任意
 Scala的访问权限:
    private       :    本类
    private[包]   :    本类   包
    protected     :    本类   子类
    [default]     :    任意

方法

Java中默认提供的方法: Object类中继承下来的方法

Scala中默认提供的方法: 1.Object类中继承下来的方法 2.PreDef中的方法 println() classOf[] ......

  1. asInstanceOf[Type] 转换成Type类型 isInstanceOf[Type] 判断是否是Type类型
    1. apply: apply通常会定义到伴生对象中(object修饰的类中), 用于创建伴生类对象.

构造器

Java的构造方法

 class User{
      public User(){}
      public User(String name){ this.name = name }
   }

Scala的构造方法: Scala是完全面向对象的语言. Scala是完全面向函数式编程的语言. 类也是一个 函数. 类名就是函数名, 类体就是函数体. 把这个特殊的函数,就称之为构造函数.

Scala中其实有两种构造函数 主构造函数 : 主要的作用就是完成类体的初始化. 辅助构造函数 : 辅助构造函数就是辅助主构造函数进行类体的初始化. def this(参数列表){} 辅助构造函数必须直接或者间接的调用主构造函数

 class User11(addr:String){
    val name:String = "zhangsan"
    println("constructor user11")
    
    def this(){
     this("beijing")
   }
    def this(name:String ,age:Int){
      this("shanghai")
    }
 }

在Scala中类的主构造函数中,在声明参数的时候,如果使用var 或者val来修饰, 该参数会直接成为类的属性.

 class User122( @BeanProperty var name:String ,val age:Int){
   def this(username:String){
     this(username,40)
   }
 }

Scala构造函数的定义顺序: 被调用的辅助构造器必须定义当前构造器的前面.

高阶面向对象编程

继承

Scala中的继承也是单继承,且使用extends关键字

封装

1) 将属性进行私有化

2) 提供一个公共的set方法,用于对属性赋值

3) 提供一个公共的get方法,用于获取属性的值

抽象

抽象就是表示 不具体 不完整。 抽象类 抽象方法

  • 一个类中如果声明了抽象方法, 那么这个类一定是抽象类
  • 一个抽象类中不一定有抽象方法.
  • Scala中除了我们熟悉的抽象类 抽象方法外, 还有一个抽象属性.
  • 在Scala中,子类继承了抽象类后,抽象类中的抽象方法,在子类中只需要补充完整即可.
  • 抽象类中的具体的方法,如果子类要重写,需要通过override修饰符来修饰.
  • 一个类中声明了抽象属性,该类必须声明为抽象的.
  • 继承了抽象类后,需要将抽象类中的抽象属性补充完整.
  • 抽象类中的val声明的具体的属性才能被子类重写.var不可以
  • 所谓的抽象属性实际上对应的是Scala为属性默认提供的 "get" / "set" 方法,对抽象属性的重写实际上对属性对应的"get" / "set" 方法的重写.

单例对象

在scala中可以通过object伴生对象来创建单例

 class User { // 伴生类
 }
 object User { // 伴生对象
     def apply() = new User() // 构造伴生类对象
 }

特质

基础语法

 trait 特质名称
 class 类名 extends 父类(特质1) with 特质2 with特质3
 trait Operator {
 }
 trait DB{
 }
 class MySQL extends Operator with DB{
 }

Java中的接口: 通过一个特殊的对象,将一些标准或者是规范进行封装. 这个对象称之为接口. 如果一个类需要按照一定的规范完成一些功能,那么该类就需要实现对应的接口

Scala中的特质: 通过一个特殊的对象, 将一些类共通的特征抽取出来进行封装,这个对象称之为特质. 如果一个类符合某个特质,那么就可以将对应的特质 "混入"到该类中.

可以将Scala中的特质理解为Java中的接口. 又可以理解是Java中的抽象类.

如果将Scala中的特质理解为接口:

  • 接口可以继承接口. 特质可以继承特质
  • 接口可以多实现. 特质可以多混入

如果将Scala中的特质理解为抽象类:

  • 抽象类中可以有抽象方法,抽象属性 , 特质也可以声明抽象方法 抽象属性
  • 类是单继承. "特质也是单继承"

动态混入

 val mysql = new MySQL with Operator
 //在创建对象的时候混入特质

初始化叠加

初始化顺序: 按照特质混入的顺序从左到右进行初始化

功能化叠加

功能执行顺序: 按照混入特质的顺序从右往左执行.

五、集合

Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质。对于几乎所有的集合类,Scala都同时提供了可变和不可变的版本。

不可变集合包:scala.collection.immutable

可变集合包:scala.collection.mutable

数组

不可变数组

 //创建数组
 val arr01 = new Array[Int](4)
 val arr1 = Array(1,2,3,4)
 val arr2 = Array(5,6,7,8)
 // 添加数组元素,创建新数组
 val arr3: Array[Int] = arr1 :+ 5
 val arr4: Array[Int] = arr1 ++ arr2
 // 多维数组
 var myMatrix = Array.ofDim[Int](3,3)
 // 合并数组
 val arr6: Array[Int] = Array.concat(arr1, arr2)
 // 创建指定范围的数组
 val arr7: Array[Int] = Array.range(0,2)
 // 创建并填充指定数量的数组
 val arr8:Array[Int] = Array.fill[Int](5)(-1)

可变数组

 //创建数组
 val buffer = new ArrayBuffer[Int]
 val buffer1 = ArrayBuffer(1,2,3,4)
 val buffer2 = ArrayBuffer(5,6,7,8)
 //增加数据
 buffer.append(1,2)
 //修改数据
 buffer.update(0,5)
 buffer(1)=6
 //删除数据
 val i:Int = buffer.remove(2)
 buffer.remove(2,2)
 // 使用 ++ 运算符会产生新的集合数组
 val buffer4: ArrayBuffer[Int] = buffer1 ++ buffer2
 // 使用 ++= 运算符会更新之前的集合,不会产生新的数组
 val buffer5: ArrayBuffer[Int] = buffer1 ++= buffer
 // 将不可变数组转换为可变数组
  val buffer1: mutable.Buffer[Int] = array.toBuffer
 // 将可变数组转换为不可变数组
 val array1: Array[Int] = buffer.toArray

Seq集合

不可变List

 //创建集合
 val list = List(1,2,3,4)
 val list3: List[Int]  = 1::2::3::Nil
 // 增加数据
 val list1: List[Int] = list :+ 1
 val list2: List[Int] = 1 +: list
 //修改数据
 val list3: List[Int] = list.updated(1,5)
 //空集合
 List()=nil
 // 合并集合
 val list5: List[Int] = List.concat(list3, list4)
 // 创建一个指定重复数量的元素列表
 val list6: List[String] = List.fill[String](3)("a")

可变List

 // 可变集合
  val buffer = new ListBuffer[Int]()
  val buffer1 = ListBuffer(1,2,3,4)
  val buffer2 = ListBuffer(5,6,7,8)
 // 增加数据
 buffer.append(1,2,3,4)
 val buffer3: ListBuffer[Int] = buffer1 :+ 5
 val buffer4: ListBuffer[Int] = buffer1 += 5
 val buffer5: ListBuffer[Int] = buffer1 ++ buffer2
 val buffer6: ListBuffer[Int] = buffer1 ++= buffer2
 // 修改数据
 buffer.update(1,3)
 // 删除数据
 buffer.remove(2)
 buffer.remove(2,2)
 // 获取数据
 println(buffer(1))
 // 遍历集合
 buffer.foreach(println)
 // 可变集合转变为不可变集合
 val list1: List[Int] = buffer.toList
 // 不可变集合转变为可变集合
 val buffer1: mutable.Buffer[Int] = list.toBuffer

Set集合

不可变Set

 //创建集合
 val set1 = Set(1,2,3,4)
 val set2 = Set(5,6,7,8)
 // 增加数据
 val set3: Set[Int] = set1 + 5 + 6
 val set4: Set[Int] = set1.+(6,7,8)
 // 删除数据
 val set5: Set[Int] = set1 - 2 - 3
 ​
 val set6: Set[Int] = set1 ++ set2
 val set7: Set[Int] = set2 ++: set1

可变集合Set

 import scala.collection.mutable
 //创建集合
 val set1 = mutable.Set(1,2,3,4)
 val set2 = mutable.Set(5,6,7,8)
 // 增加数据
 set1.add(5)
 // 添加数据
 set1.update(6,true)
 println(set1.mkString(","))
 // 删除数据
 set1.update(3,false)
 println(set1.mkString(","))
 // 删除数据
 set1.remove(2)
 println(set1.mkString(","))
 // 遍历数据
 set1.foreach(println)
 // 交集
 val set3: mutable.Set[Int] = set1 & set2
 // 差集
 val set4: mutable.Set[Int] = set1 &~ set2

Map集合

不可变Map

 //创建map
 val map1 = Map( "a" -> 1, "b" -> 2, "c" -> 3 )
 val map2 = Map( "d" -> 4, "e" -> 5, "f" -> 6 )
 // 添加数据
 val map3 = map1 + ("d" -> 4)
 println(map1 eq map3) // false
 // 删除数据
 val map4 = map3 - "d"
 println(map4.mkString(","))
 val map5: Map[String, Int] = map1 ++ map2
 println(map5 eq map1)
 println(map5.mkString(","))
 val map6: Map[String, Int] = map1 ++: map2
 println(map6 eq map1)
 println(map6.mkString(","))
 // 修改数据
 val map7: Map[String, Int] = map1.updated("b", 5)
 println(map7.mkString(","))
 // 遍历数据
 map1.foreach(println)
 // 创建空集合
 val empty: Map[String, Int] = Map.empty
 println(empty)
 // 获取指定key的值
 val i: Int = map1.apply("c")
 println(i)

可变Map

 import scala.collection.mutable
 //创建map
 val map1 = mutable.Map( "a" -> 1, "b" -> 2, "c" -> 3 )
 val map2 = mutable.Map( "d" -> 4, "e" -> 5, "f" -> 6 )
 // 添加数据
 map1.put("d", 4)
 val map3: mutable.Map[String, Int] = map1 + ("e" -> 4)
 println(map1 eq map3)
 val map4: mutable.Map[String, Int] = map1 += ("e" -> 5)
 println(map1 eq map4)
 // 修改数据
 map1.update("e",8)
 map1("e") = 8
 // 删除数据
 map1.remove("e")
 val map5: mutable.Map[String, Int] = map1 - "e"
 println(map1 eq map5)
 val map6: mutable.Map[String, Int] = map1 -= "e"
 println(map1 eq map6)
 // 清除集合
 map1.clear()
 //基本操作
 val set: Set[(String, Int)] = map1.toSet
 val list: List[(String, Int)] = map1.toList
 val seq: Seq[(String, Int)] = map1.toSeq
 val array: Array[(String, Int)] = map1.toArray
 ​
 println(map1.get("a"))
 println(map1.getOrElse("a", 0))
 ​
 println(map1.keys)
 println(map1.keySet)
 println(map1.keysIterator)
 println(map1.values)
 println(map1.valuesIterator)
 ​

元组

 // 创建元组,使用小括号
 val tuple = (1, "zhangsan", 30)
 // 根据顺序号访问元组的数据 
 println(tuple._1)
 println(tuple._2)
 println(tuple._3)
 // 迭代器
 val iterator: Iterator[Any] = tuple.productIterator
 // 根据索引访问元素
 tuple.productElement(0)
 // 获取整体
 println(tuple)
 // 如果元组的元素只有两个,那么我们称之为对偶元组,也称之为键值对
 val kv: (String, Int) = ("a", 1)
 val kv1: (String, Int) = "a" -> 1

队列

 val que = new mutable.Queue[String]()
 // 添加元素
 que.enqueue("a", "b", "c")
 val que1: mutable.Queue[String] = que += "d"
 println(que eq que1)
 // 获取元素
 println(que.dequeue())
 println(que.dequeue())
 println(que.dequeue())
 ​

并行

 val result1 = (0 to 100).map{x => Thread.currentThread.getName}
 //并行多线程启动
 val result2 = (0 to 100).par.map{x => Thread.currentThread.getName}
 ​

常用方法

1) 常用方法

 object ScalaCollection{
     def main(args: Array[String]): Unit = {
         val list = List(1,2,3,4)
 ​
         // 集合长度
         println("size =>" + list.size)
         println("length =>" + list.length)
         // 判断集合是否为空
         println("isEmpty =>" + list.isEmpty)
         // 集合迭代器
         println("iterator =>" + list.iterator)
         // 循环遍历集合
         list.foreach(println)
         // 将集合转换为字符串
         println("mkString =>" + list.mkString(","))
         // 判断集合中是否包含某个元素
         println("contains =>" + list.contains(2))
         // 取集合的前几个元素
         println("take =>" + list.take(2))
         // 取集合的后几个元素
         println("takeRight =>" + list.takeRight(2))
         // 查找元素
         println("find =>" + list.find(x => x % 2== 0))
         // 丢弃前几个元素
         println("drop =>" + list.drop(2))
         // 丢弃后几个元素
         println("dropRight =>" + list.dropRight(2))
         // 反转集合
         println("reverse =>" + list.reverse)
         // 去重
         println("distinct =>" + list.distinct)
     }
 }
 ​

2) 衍生集合

 object ScalaCollection{
     def main(args: Array[String]): Unit = {
         val list = List(1,2,3,4)
         val list1 = List(3,4,5,6)
 ​
         // 集合头
         println("head => " + list.head)
         // 集合尾
         println("tail => " + list.tail)
         // 集合尾迭代
         println("tails => " + list.tails)
         // 集合初始化
         println("init => " + list.init)
         // 集合初始化迭代
         println("inits => " + list.inits)
         // 集合最后元素
         println("last => " + list.last)
         // 集合并集
         println("union => " + list.union(list1))
         // 集合交集
         println("intersect => " + list.intersect(list1))
         // 集合差集
         println("diff => " + list.diff(list1))
        
        // 切分集合
         println("splitAt => " + list.splitAt(2))
         // 滑动
         println("sliding => " + list.sliding(2))
         // 滚动
         println("sliding => " + list.sliding(2,2))
         // 拉链
         println("zip => " + list.zip(list1))
         // 数据索引拉链
         println("zipWithIndex => " + list.zipWithIndex)
     }
 }

3) 计算函数

 object ScalaCollection{
     def main(args: Array[String]): Unit = {
         val list = List(1,2,3,4)
         val list1 = List(3,4,5,6)
 ​
         // 集合最小值
         println("min => " + list.min)
         // 集合最大值
         println("max => " + list.max)
         // 集合求和
         println("sum => " + list.sum)
         // 集合乘积
         println("product => " + list.product)
         // 集合简化规约
         println("reduce => " + list.reduce((x:Int,y:Int)=>{x+y}))
         println("reduce => " + list.reduce((x,y)=>{x+y}))
         println("reduce => " + list.reduce((x,y)=>x+y))
         println("reduce => " + list.reduce(_+_))
         // 集合简化规约(左)
         println("reduceLeft => " + list.reduceLeft(_+_))
         // 集合简化规约(右)
         println("reduceRight => " + list.reduceRight(_+_))
         // 集合折叠
         println("fold => " + list.fold(0)(_+_))
         // 集合折叠(左)
         println("foldLeft => " + list.foldLeft(0)(_+_))
         // 集合折叠(右)
         println("foldRight => " + list.foldRight(0)(_+_))
         // 集合扫描
         println("scan => " + list.scan(0)(_+_))
         // 集合扫描(左)
         println("scanLeft => " + list.scanLeft(0)(_+_))
         // 集合扫描(右)
         println("scanRight => " + list.scanRight(0)(_+_))
     }
 }

4) 功能函数

 object ScalaCollection{
     def main(args: Array[String]): Unit = {
         val list = List(1,2,3,4)
 ​
         //map: 集合映射,将集合通过指定的转换规则转换成新的集合
        def transform(i:Int):Int ={
              i * 2
         }
         println("map => " + list.map(transform)) // 使用自己定义函数
         println("map => " + list.map(x=>{x*2}))  // 匿名函函数
         println("map => " + list.map(x=>x*2))
         println("map => " + list.map(_*2))
 ​
 ​
         //flatten: 集合扁平化,所谓的扁平化就是将整体拆分成一个一个的个体
         // 将如下集合处理成 List(1,2,3,4)
         val list1 = List(
             List(1,2),
             List(3,4)
         )
         println("flatten =>" + list1.flatten)
        
        // 将如下集合处理成List(1,2,3,4)     
        val list2 = List(List(List(1,2)),List(List(3,4)))
            println("flatten =>" + list2.flatten.flatten) // 递归
             
         // flatMap:  集合扁平映射
         // 将如下集合处理成 List(2,4,6,8)
         val list3 = List( List(1,2),List(3,4))
         // 方法一
         println("flatMap =>" + list3.flatten.map(_ * 2)) // 先flatten再map
 ​
         def transform1(list:List[Int]):List[Int] = {
               list.map( _ * 2)
          }
         // 方法二
         println("flatMap =>" +list3.flatMap(transform1)) //使用自己定义函数
         // 方法三
         println("flatMap =>" +list3.flatMap(list=>list.map(_*2))) // 匿名函数
         println("flatMap =>" +list3.flatMap(_.map(_ * 2)))
        
         // 将如下集合处理成List("hello", "scala","hello","spark")
         val list4 = List("hello scala","hello spark") 
 ​
         println("flatMap =>" +list4.flatten) //默认拆分成一个一个的字符
 ​
         println("flatMap =>" +list4.flatMap(_.split(" "))) //自己定义扁平规则
         
         
         
         
         //filter: 集合过滤数据,按照指定的规则对集合中的每条数据进行筛选过滤,满足条件的保留
 //,不满足条件的丢弃
 val list5 = List(1,2,3,4)
 ​
 println("filter =>" +list5.filter(_ % 2 == 0)) //过滤偶数
 ​
 val list6 = List("hello","spark","scala","hadoop")
 ​
 println("filter =>" +list6.filter(_.startsWith("s"))) //过滤”s”开头的单词
        
       
 ​
        // groupBy: 集合分组数据,按照指定的规则对集合中的每个数据进行分组,指定的规则其实就
 // 是一个函数,这个函数返回的结果就是分组的 key.
 val list7 = List(1,2,3,4)
 println("groupBy =>" +list7.groupBy(_ % 2)) 
 ​
 val list8 = List("hello","hello","scala","haha")
 println(list8.groupBy(word=>word)) // 单词分组
 println("groupBy =>" +list8.groupBy(_.charAt(0))) // 单词首字母分组
 ​
 ​
         //sortBy: 集合排序,将集合中每个数据按照指定的规则进行排序
         val list9 = List(3,1,4,2)
         println(list9.sortBy(num => num)) 
         println(list9.sortBy(num => -num)) //降序排序
         println("sortBy =>" + list.sortBy(num=>num)(Ordering.Int.reverse))//降序排序
       
        val list10 = List((30,"zhangsan"),(20,"wangwu"),(20,"lisi"))
 ​
            println(list10.sortBy(t => t)(Ordering.Tuple2(Ordering.Int.reverse, Ordering.String)))
 ​
        //sortWith: 自定义排序
 ​
      // 大 > 小  降序
       // 小 < 大  升序
       println(ints2.sortWith((left, right) => {
            //left._1 > right._1 // 降序
            // left._1 < right._1 // 升序
            if(left._1 == right._1){ //
                left._2 >  right._2
            }else{
                left._1 > right._1
            }
        }))
     }
 }

六、模式匹配

基本语法

 var operator: Char = '+'
         var result = operator match {
             case '+' => a + b
             case '-' => a - b
             case '*' => a * b
             case '/' => a / b
             case _ => "illegal"
         }

匹配规则

匹配常量

 def describe(x:Any)=x match{
     case 5 => "Int five"
     case "hello" => "String hello"
     case true => "Boolean true"
     case '+' => "Char +"
 }

匹配类型

 def describe(x: Any) = x match {
     case i: Int => "Int"
     case s: String => "String hello"
     case m: List[_] => "List"
     case c: Array[Int] => "Array[Int]"
     case someThing => "something else " + someThing
 }

匹配数组

 for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对一个数组集合进行遍历
     val result = arr match {
         case Array(0) => "0" //匹配Array(0) 这个数组
         case Array(x, y) => x + "," + y //匹配有两个元素的数组,然后将将元素值赋给对应的x,y
         case Array(0, _*) => "以0开头的数组" //匹配以0开头的数组
         case _ => "something else"
     }
     println("result = " + result)
 }

匹配列表

 for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 0, 0), List(88))) {
     val result = list match {
         case List(0) => "0" //匹配List(0)
         case List(x, y) => x + "," + y //匹配有两个元素的List
         case List(0, _*) => "0 ..."
         case _ => "something else"
     }
 ​
     println(result)
 }
 val list: List[Int] = List(1, 2, 5, 6, 7)
 list match {
     case first :: second :: rest => println(first + "-" + second + "-" + rest)
     case _ => println("something else")
 }

匹配元组

 for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {
     val result = tuple match {
         case (0, _) => "0 ..." // 第一个元素是0的元组
         case (y, 0) => "" + y + "0" // 匹配后一个元素是0的对偶元组
         case (a, b) => "" + a + " " + b
         case _ => "something else" //默认
     }
     println(result)
 }

匹配对象

 val user: User = User("zhangsan", 11)
 val result = user match {
     case User("zhangsan", 11) => "yes"
     case _ => "no"
 }
 //样例类
 case class User(name: String,age: Int)

样例类

  • 样例类就是使用case关键字声明的类
  • 样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中自动提供了一些常用的方法,如apply、unapply、toString、equals、hashCode和copy。
  • 样例类是为模式匹配而优化的类,因为其默认提供了unapply方法,因此,样例类可以直接使用模式匹配,而无需自己实现unapply方法。
  • 构造器中的每一个参数都成为val,除非它被显式地声明为var(不建议这样做)

应用场景

 //变量声明
 val (x, y) = (1, 2)
 val Array(first, second, _*) = Array(1, 7, 2, 9)
 val Person(name, age) = Person("zhangsan", 16)
 case class Person(name: String, age: Int)
 //循环匹配
 val map = Map("A" -> 1, "B" -> 0, "C" -> 3)
 for ((k, v) <- map if v >= 1) { //直接将map中的k-v遍历出来
    println(k + " -> " + v) //3个
 }
 //函数参数
 val list = List(("a",1),("b",2),("c",3))
 val newList1: List[(String, Int)] = list.map {
       case (word, count) => {
         (word, count * 2)
       }
     }

偏函数

基本语法

 // 声明偏函数
 val pf: PartialFunction[Int, String] = { case 1 => "one" }
 // 应用偏函数
 println(List(1, 2, 3, 4).collect(pf))

七、异常处理

Scala中的异常不区分所谓的编译时异常和运行时异常,也无需显示抛出方法异常,所以Scala中没有throws关键字。

 object ScalaException {
     def main(args: Array[String]): Unit = {
         try {
             var n= 10 / 0
         }catch {
             case ex: ArithmeticException=>{
                 // 发生算术异常
                 println("发生算术异常")
             }
             case ex: Exception=>{
                 // 对异常处理
                 println("发生了异常1")
             }
         }finally {
             println("finally")
         }
     }
 }

八、隐式转换

Scala在程序编译错误时,可以通过隐式转换中类型转换机制尝试进行二次编译,将本身错误无法编译通过的代码通过类型转换后编译通过。

隐式函数

 implicit def transform( d : Double ): Int = {
             d.toInt
         }
         var d : Double = 2.0
         val i : Int = d
         println(i)
     }

隐式参数与隐式变量

 object ScalaImplicit {
    // 隐式参数  
    def regUser(name:String)(implicit password:String="666"):Unit = {
      println(s"注册用户: $name ,默认密码: $password ")
    }
     //TODO 隐式变量
 implicit val newPassword:String = "888"
 //如果想要使用隐式参数进行处理, 那么调用函数时, 不需要使用小括号调用
 regUser("zhangsan")
 //如果想要使用参数的默认值或者自己传入值,就加上小括号
 regUser("zhangsan")()
 regUser("zhangsan")("999")
 //TODO 隐式参数和隐式变量举例
 //集合的sortBy方法
 }

隐式类

  • 其所带的构造参数有且只能有一个
  • 隐式类必须被定义在“类”或“伴生对象”或“包对象”里,即隐式类不能是顶级的。
 implicit class User( emp : Emp) {
         def insertUser(): Unit = {
             println("insert user...")
         }
     }

隐式机制

所谓的隐式机制,就是一旦出现编译错误时,编译器会从哪些地方查找对应的隐式转换规则

  • 当前代码作用域
  • 当前代码上级作用域
  • 当前类所在的包对象
  • 当前类(对象)的父类(父类)或特质(父特质)

九、泛型

泛型不可变

 class Test[T] { }
 val test1 : Test[User] = new Test[User] // OK
 val test2 : Test[User] = new Test[Parent] // Error
 val test3 : Test[User] = new Test[SubUser]  // Error

泛型协变

 // 泛型协变[+T]:就是将子类型当成父类型来使用
 class Test[+T] { }
 val test1 : Test[User] = new Test[User] // OK
 val test2 : Test[User] = new Test[Parent] // Error
 val test3 : Test[User] = new Test[SubUser]  // OK

泛型逆变

 //泛型逆变[-T]: 将父类型当成子类型来使用
 class Test[-T] { }
 val test1 : Test[User] = new Test[User] // OK
 val test2 : Test[User] = new Test[Parent] // OK
 val test3 : Test[User] = new Test[SubUser]  // Error

泛型边界

 def  test[A]( a : A ): Unit = {
    println(a)
 }
 test[User](parent) // Error
 test[User](user)   // OK
 test[User](subuser) // OK

泛型上限

 //对比java   ? extends User
 def  test[A<:User]( a : A ): Unit = {
    println(a)
 }

泛型下限

 //对比java  ? super User
 def  test[A>:User]( a : A ): Unit = {
     println(a)
 }

上下文限定

 //函数f的泛型为[A:Test],也就是说后面需要一个隐式转换的Test[A]的参数A
 def f[A : Test](a: A) = println(a)
 //此隐式转换符合要求
 implicit val test : Test[User] = new Test[User]
 //f的参数类型为User
 f( new User() )
 ​
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值