Scala 函数、Scala 集合

Scala函数

面向对象编程和面向函数编程

Scala中函数的定义

函数类型的定义

函数的简写

lambda表达式 --- 匿名函数

package com.shujia.scala

object Demo14Fun1 {
  def main(args: Array[String]): Unit = {
  
    /**
      * 面向对象编程 : 将对象传来传去
      * 1、将对象作为参数
      * 2、将对象作为返回值
      *
      * 需要明确对象的类型
      *
      *
      * 面向函数编程 : 将函数传来传去
      * 1、可以将一个函数作为参数
      * 2、可以将一个函数作为返回值
      *
      * 所以需要明确每一个函数的类型
      *
      */


    /**
      * scala中函数的定义
      * 1、可以在object创建 : 通过对象名直接调用
      * 2、可以类中创建 : 需要创建类的对象才能调用
      * 3、可以在任何代码块中创建 : 可以直接在后面调用
      *
      * 函数的基本要素
      * 1、函数名
      * 2、函数的参数列表
      * 3、函数的返回值
      * 4、函数体
      *
      * 使用函数的时候,要注意函数的作用域
      *
      * 在同一个代码块中不能出现同名的函数
      */

    def fun1(): Unit = {
      println("fun1")
    }

    //调用函数、函数可以多次调用
    fun1()
    fun1()

    /**
      * 函数类型的定义
      * 1、函数的类型 与 函数的 参数 和 返回值 有关
      *
      *
      * def add(i: Int): Int = {
      * i + 1
      * }
      * 函数类型的描述: 这是一个参数为Int类型返回值为Int类型的函数
      *
      * 函数类型的表示方式: Int => Int
      *
      */

    def add(i: Int): Int = {
      i + 1
    }

    val j: Int = add(100)

    println(j)


    //这是一个参数为String 返回值为Int类型的函数
    def fun2(str: String): Int = {
      str.toInt
    }


    //这是一个参数为String没有返回值的函数
    def fun3(str: String): Unit = {
      println(str)
    }

    /**
      *
      * 函数的简写
      * 1、如果函数体只有一行 {} 可以省略
      * 2、如果最后一行作为返回值return可以省略
      * 3、如果没有参数,()  可以省略
      * 4、返回值类型可以省略,会自动推断
      *
      */

    def fun4(str: String): Unit = println(str)


    /**
      * lambda表达式 --- 匿名函数
      *
      * (str: String) => str.toInt
      *
      * => : 左边是参数
      * => : 右边是函数体
      *
      */

    // 这是一个参数为String 返回值为Int类型的函数
    // 这相当于用一个变量来接收 lambda 表达式(匿名函数)
    // 注意 : String => Int 和 (str: String) => str.toInt
    // String => Int -- 描述函数类型
    // (str: String) => str.toInt -- lambda 表达式
    
    val fun5: String => Int = (str: String) => str.toInt
    //  在代码块中,直接调用
    val k: Int = fun5("10004")

    println(k)
    
     
    def fun6(i: Int): Int = {
      i * 100
    }

    //函数的调用
    val i2: Int = fun6(1000)

    //将函数赋值给一个变量
    val f7: Int => Int = fun6

  }
}

函数的应用

以函数作为参数 --重点

以函数作为参数的简写

以函数作为参数的应用

foreach 函数

package com.shujia.scala

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

    /**
      * 函数的应用
      *
      * 高阶函数
      *
      * 1、以函数作为参数   --重点
      * 2、以函数作为返回值
      *
      */

    /**
      * 
      * 以函数作为参数
      *
      * f: 是一个参数为String 返回值为Int类型的函数
      *
      * fun1 是什么类型的函数?
      * fun1是一个参数为f 没有返回值的函数
      *
      */

    def fun1(f: String => Int): Unit = {

      // 调用传进来的函数
      val i: Int = f("100")

      println(i)

    }

    // 一个参数为String 返回值为Int类型的函数
    def f1(str: String): Int = {
      str.toInt
    }

    // 调用fun1() 需要传入一个参数为String 返回值为Int类型的函数
    fun1(f1)

    // 这边传入不同的函数、仔细体会面向函数编程的思想
    def f2(str: String): Int = {
      (str + "1232123").toInt
    }

    fun1(f2)


    /**
      * 使用 lambda 作为参数
      * 就是匿名函数的传递
      */

    fun1((s: String) => {
      val i: Int = s.toInt
      //最后一行作为返回值
      i
    })

    /**
      * 上面的简写
      * lambda 表达式的简写
      */
    // 1、如果代码只有一行括号可以省略
    fun1((s: String) => s.toInt)

    // 2、lambda 的参数类型可以省略
    // lambda 表达式参数的类型会自动推断
    fun1(s => s.toInt)

    // 3、如果lambda的参数只使用了一次可以使用下划线代替
    fun1(_.toInt)


    println("=" * 100)

    /**
      * 以函数作为参数的应用
      *
      */

    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

    /**
      * foreach : 遍历数组中的元素, 并将 遍历出来的元素 作为参数 传递给 作为参数传入 foreach 括号中的函数
      *
      * foreach 将循环之后需要做的处理交给调用者,由调用者传入一个函数进去处理
      */
    arr.foreach((i: Int) => {
      println(i)
    })

    println("=" * 100)
    
    //简写
    arr.foreach(i => println(i))

    arr.foreach(println(_))

    println("=" * 100)
    /**
      * println 是一个参数为Any 没有返回值的函数
      *
      * arr.foreach 需要的是参数为Int 没有返回值的函数
      *
      * scala函数的调用也符合多态的思想
      *
      */
    arr.foreach(println)
  }
}

以函数作为返回值 -- 不常用

调用返回的函数并简化调用过程

函数柯里化

package com.shujia.scala

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

    /**
      * 以函数作为返回值 -- 不常用
      *
      */

    // fun1 是一个 参数为 String 返回值为 一个 参数为 String 返回值为 Int 的函数
    def fun1(str: String): String => Int = {

      def f(s: String): Int = {
        (s + str).toInt
      }

      // 返回一个函数
      f
    }

    // 调用fun1 返回一个函数,并用变量f2接收
    // 所以f2是一个 参数为String 返回值为Int 的函数
    val f2: String => Int = fun1("123213")

    //调用返回的函数
    val i: Int = f2("222")

    println(i)


    // 简化调用过程
    // fun1("111") -- 相当于上面的 f2
    // fun1("111")("222") -- 相当于 f2("222")
    val j: Int = fun1("111")("222")

    // 上面 fun1 函数的改写 不要函数的返回值是一个函数
    def fun3(str: String, s: String): Int = {
      (s + str).toInt
    }

    val k: Int = fun3("333", "444")

    /**
      * 上面 fun1 函数的简写
      *
      * 这里并不是上面 fun3 函数那样将 fun1 函数改写
      *
      * 函数柯里化
      *
      */

    def fun2(str: String)(s: String): Int = {
      (s + str).toInt
    }
    // 可以一次性给两个函数传参
    val i2: Int = fun2("555")("6666")
    println(i2)

    /**
      * 也可以先给第一个函数传参 再 给后面的函数传参
      */
    val f4: String => Int = fun2("777")

    val i4: Int = f4("888")
    val i5: Int = f4("999")

  }
}

一个函数的参数和返回值都是一个函数的情况

package com.shujia.scala

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


    /**
      * 参数和返回值都是一个函数
      *
      */
      
    def fun1(f: String => String): String => String = {
      f
    }

    // 这里用变量接收一下 fun1 观察一下 fun1 的类型
    // val f: (String => String) => String => String = fun1

    // 调用 fun1
    val f1: String => String = fun1((s: String) => s)

    val str: String = f1("shujia")

    println(str)

  }
}

map 函数

package com.shujia.scala

object Demo18Fun5 {
  def main(args: Array[String]): Unit = {
    val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)

    /**
      * 将arr中的数据都加2
      *
      */

    var i = 0
    while (i < arr.length) {

      arr(i) = arr(i) + 2

      i += 1
    }

    arr.foreach(println)


    println("=" * 100)
    
    /**
      *
      * map: 将数组中的元素遍历并传递给后面的函数
      * map会将后面的函数的返回值构建成一个新的数组
      * 返回一个新的数组
      *
      */

    val arr2: Array[Int] = arr.map((i: Int) => i + 2)

    arr2.foreach(println)

    println("=" * 100)
    
    /**
      * 将数组中的元素奇数加1,偶数乘以2
      *
      */

    val arr3: Array[Int] = arr.map((i: Int) => {
      if (i % 2 == 1) {
        i + 1
      } else {
        i * 2
      }
    })

    arr3.foreach(println)
  }
}

Scala 集合

list

package com.shujia.scala

import java.util

import scala.collection.mutable.ListBuffer
import scala.io.Source

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

    /**
      * list : 有序不唯一
      * set  : 无序唯一
      * map  : k-v结构
      * tuple: 固定长度的集合
      *
      */

    /**
      * 不可变 list -- 不能增删元素
      * 底层是数组
      * scala中的list 提供了很多实用的方法
      */

    val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 1)

    println(list.head) //获取第一个元素
    println(list.tail) //获取不包含第一个元素的所有元素
    println(list.last) //获取最后一个
    println(list.take(3)) //从左边取3个
    println(list.takeRight(3)) //从右边取3个

    println(list(2)) //通过下标获取元素

    //和split功能相反
    println(list.mkString("|")) //通过一个分隔符将集合拼接成一个字符串
    println(list.sum) //求和
    println(list.max) //获取最大值
    println(list.min) //获取最小值
    println(list.sum / list.length.toDouble) //平均值

    println(list.distinct) //去重 返回一个新的集合

    println(list.reverse) //反转集合 返回一个新的集合

    println(list.drop(1)) //从左向右删除一个元素 返回一个新的集合并不改变原集合
    println(list)


    /**
      * 高级的方法
      *
      */

    /**
      * foreach: 遍历集合中元素,并将元素一个一个传递给后面的函数
      *
      */
    var sum = 0

    list.foreach(i => {
      sum += i
    })

    println(sum)

    /**
      * map : 遍历集合中的元素并将元素一个一个传递给后面的函数,最后将后面函数的返回值构建成一个新的集合返回
      *
      */

    val list2: List[Int] = list.map((i: Int) => i + 2)
    println(list2)

    //改变集合中所有元素的类型
    val strs: List[String] = list.map((i: Int) => i.toString)
    println(strs)

    /**
      * sort
      *
      * sortBy: 通过一个字段进行排序, 默认是升序
      *
      */

    val sortList: List[Int] = list.sortBy((i: Int) => i)
    println(sortList)

    /**
      * 读取学生数据,按照年龄排序
      *
      */

    //读取文件得到一个集合
    val students: List[String] = Source.fromFile("data/students.txt").getLines().toList

    //按年龄倒序排列
    val studentSort: List[String] = students.sortBy((stu: String) => -stu.split(",")(2).toInt)
    studentSort.foreach(println)

    /**
      *
      * sortWith: 指定一个排序规则
      */
    // (i: Int, j: Int) => i > j
    // i 代表上一条数据  j 代表当前数据
    val sortList2: List[Int] = list.sortWith((i: Int, j: Int) => i > j)

    println(sortList2)


    println("=" * 100)


    val words = new util.ArrayList[String]()
    val lines = List("java,spark", "java,hadoop", "java,scala,hive", "bhase,hadoop,scala")

    for (line <- lines) {
      val split: Array[String] = line.split(",")

      for (word <- split) {
        words.add(word)
      }
    }

    println(words)

    println("=" * 100)

    /**
      *
      * 上面的逻辑可以用 flatMap 实现
      * flatMap: 遍历集合中的元素并将之一个一个传递给后面的函数,传入一行返回多行
      * flatMap 分两步
      * 1、先遍历集合中的元素并将之一个一个传递给 将来当做参数传进 flatMap 的函数
      * 2、将 将来当做参数传进 flatMap 的函数 返回的 结果 构建成一个新的集合,返回给调用者
      *
      */

    val words2: List[String] = lines.flatMap((line: String) => line.split(","))
    println(words2)


    println("=" * 100)

    /**
      * 可变list -- ListBuffer
      *
      */

    val listBuffer = new ListBuffer[String]()

    //增加元素
    listBuffer += "java"

    //增加多个元素
    listBuffer ++= List("scala", "hadoop", "java")

    println(listBuffer)

    //删除一个元素
    listBuffer -= "java"

    //删除多个元素
    listBuffer --= List("hadoop", "scala")

    println(listBuffer)

    //通过下标修改元素
    listBuffer.update(0, "hadoop")

    println(listBuffer)

    //通过下标删除元素
    listBuffer.remove(0)
    println(listBuffer)

  }
}

set

package com.shujia.scala

import scala.collection.mutable

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

    /**
      * 不可变Set
      *
      */

    val set = Set(1, 2, 3, 4, 5, 6, 7, 8, 9, 1)

    println(set)
    println(set.head)
    println(set.tail)
    println(set.last)
    println(set.sum)
    println(set.max)
    println(set.min)

    /**
      * 取出集合中的奇数
      *
      * filter : 遍历集合中的元素并将之一个一个传递给 将来当做参数传进filter的函数 , 被当做参数传进来的函数返回true保留数据,返回false过滤数据
      *
      */
    val filterSet: Set[Int] = set.filter((i: Int) => i % 2 == 1)

    println(filterSet)


    val s1 = Set(1, 2, 3, 4, 5, 6)
    val s2 = Set(3, 4, 5, 6, 7, 8, 9)

    println(s1 & s2)  //交集
    println(s1 | s2)  //并集
    println(s1 &~ s2) //差集


    /**
      * list set map array 都有以下方法
      * map
      * flatMap
      * filter
      * foreach
      * groupBy
      *
      * set 集合不能排序, set map 不能反转
      */


    /**
      * 可变Set -- mutable.HashSet
      * mutable -- 可变
      * imutable -- 不可变
      */
      
    // 因为有 伴生对象、apply方法 所以不用 new 也行
    // val hashSet = mutable.HashSet()
    
    val hashSet = new mutable.HashSet[String]()

    //增加元素
    // += 和 add 是一样的
    hashSet.add("java")
    hashSet += "scala"

    println(hashSet)
    
    //移除元素
    // -= 和 remove 是一样的
    hashSet.remove("java")
    hashSet -= "scala"
    println(hashSet)

    //可变集合转换成不可变集合
    //只要涉及到转化 就是 to
    val set2: Set[String] = hashSet.toSet

  }
}

tuple

package com.shujia.scala

object Demo21Tuple {
  def main(args: Array[String]): Unit = {
    /**
      * 元组 -- 元组是不可变的
      * 可以通过下标获取元素
      * 相比较数组不会出现下标越界的问题
      * 元组中的类型没有限制,每个元素的类型都是独立的
      * 元组最多只能存放22个元素
      */

    // Tuple7 -- 表示含有7个元素的元组,可以省略,Scala会自动推断
    // 这个元组 可以称为 7元组
    val tuple = Tuple7(1, 2, 3, 4, 5, 6, "asd")

    println(tuple._7)

    //简写
    val t2 = (1, 2, 3, 4)
    println(t2)

    //可以通过多个变量接收
    //(id, name, age) 这个代表定义多个变量一起接收这个元组
    val (id, name, age) = ("001", "张三", 23)

    println(id)
    println(name)
    println(age)

  }
}

map

package com.shujia.scala

import scala.collection.{immutable, mutable}

object Demo22Map {
  def main(args: Array[String]): Unit = {
    /**
      * 不可变 map
      * Map 需要传入 k-v  使用二元组构建 k-v
      * "003" -> "王五" 构建二元组的简写
      */
    val map = Map(("001", "张三"), ("002", "李四"), "003" -> "王五")

    println(map)

    //通过key 获取value
    println(map("003"))

    //如果 key 存在返回 value 如果 key 不存在返回后面的默认值
    println(map.getOrElse("001", "默认值"))

    /**
      * Map 集合的map方法 传给 将来当做参数传进map()的函数 的参数是一个二元组,可以通过下标获取key和value
      *
      */

    val values = map.map((kv: (String, String)) => kv._2)

    println(values)


    //获取key和value
    println(map.values)
    println(map.keys)


    //遍历map
    map.foreach(println)

    /**
      * 可变的map -- mutable.HashMap
      *
      */

    val hashMap = new mutable.HashMap[String, String]()

    //保存元素
    hashMap.put("001", "张三")

    hashMap.+=(("002", "李四"))

    hashMap += "003" -> "王五"

    println(hashMap)

    //删除元素
    hashMap.remove("001")
    hashMap -= "002"

    println(hashMap)

  }
}
posted @ 2022-03-04 23:11  赤兔胭脂小吕布  阅读(48)  评论(0编辑  收藏  举报