一门多范式的编程语言Scala学习的第二天-函数的使用

2.12 scala中的函数式编程

* scala中的函数式编程
*
* 面向对象编程:将对象当作参数一样传来传去
* 1、对象可以当作方法参数传递
* 2、对象也可以当作方法的返回值返回
* 当看到类,抽象类,接口的时候,今后无论是参数类型还是返回值类型,都需要提供对应的实现类对象
*
* 面向函数式编程:将函数当作参数一样传来传去
* 1、函数A当作函数B的参数进行传递
* 2、函数A当作函数B的返回值返回
*
* 在scala中,将函数也当作一个对象,对象就有类型
* 函数在scala也有类型的说法
* 参数类型=>返回值类型
object Demo10fun {
  def main(args: Array[String]): Unit = {

    //是一个参数是字符串类型,返回值是整数类型的函数
    def fun1(a1:String):Int={
      a1.toInt
    }

    val res1: Int = fun1("1000")
    println(res1)

    //定义变量的方式,定义一个函数
    //将函数当作对象,赋值给类型是函数类型的变量,将来可以直接通过变量调用函数
    val fun2:String=>Int=fun1
    val res2: Int = fun2("2000")
    println(res2)

    /**
     * 函数A作为函数B的参数定义
     *
     * 本质上是将函数A的处理逻辑主体传给了函数B,在函数B中使用这个处理逻辑
     */
    //f:String=>Int  相当于函数A
    //fun3相当于函数B
    def fun3(f:String=>Int):Int={
      val a1:Int=f("100")
      a1+100
    }

    def show1(a1:String):Int=a1.toInt

    val res4: Int = fun3(show1)
    println(res4)

    def show2(a1: String): Int = a1.toInt+100

    val res5: Int = fun3(show2)
    println(res5)

    //定义一个函数fun1, 函数的参数列表中,既有正常的类型参数,也有函数类型的参数
    def fun4(s:String,f:String=>Int): Int = {
      val b1:Int=f(s)
      b1+111
    }

    def show3(a1: String): Int = a1.toInt + 100

    val res6: Int = fun4("1000",show3)
    println(res6)


    //使用lambda表达式改写函数作为参数传递的调用形式
    fun4("100",(s:String)=>s.toInt)
    fun4("100",(s:String)=>s.toInt+100)

    //在Scala中数据类型可以自动推断
    val res7: Int = fun4("1000", s => s.toInt + 100)
    println(res7)
    ////如果当作参数的函数的参数只在函数主体使用了一次,那么可以使用_代替
    fun4("100",_.toInt+100)
  }

}

1、函数当作参数传递的应用

object Demo11fun {
  def main(args: Array[String]): Unit = {
    val arr1: Array[Int] = Array(11, 22, 33, 44, 55)

    def fun1(i:Int): Unit = {
      println(i*2)

    }
    //def foreach[U](f: A => U): Unit
    //foreach函数需要一个参数和数组元素一样类型的类型,返回值是Unit的函数
    //foreach函数的主要作用是将调用该方法的序列中的元素,依次取出传递给后面的函数进行处理
    arr1.foreach(fun1)

    // scala自带的一个函数
    // def println(x: Any) = Console.println(x)
    // Any可以接收任意的数据类型元素
    arr1.foreach(println)
  }
}

2、函数当作返回值返回

object Demo12fun {
  def main(args: Array[String]): Unit = {
    /**
     * fun1: 参数是String类型,返回值是一个函数(参数是String类型,返回值是Int)
     */
    //定义返回值是函数的函数方式1:
    def fun1(s1:String):String=>Int={
      def fun2(s2:String):Int={
        s2.toInt+s1.toInt
    }
      fun2
    }
    //调用函数的返回值是函数的方式1
    val res1: String => Int = fun1("100")
    val res2: Int = res1("100")
    println(res2)

    //定义方式2(是方式1的简化写法):
    def fun2(s1:String)(s2:String):Int={
      s1.toInt+s2.toInt
    }

    val res3: Int = fun2("1")("100")
    println(res3)
    //一般这么用方式二
    val resfun: String => Int = fun2("10")
    val res4: Int = resfun("11")
    println(res4)
    val res5: Int = resfun("22")
    println(res5)
    val res6: Int = resfun("33")
    println(res6)

    //另一种写法
    def fun3(s1:String,s2:String):Int={
      s1.toInt+s2.toInt
    }

    val res7: Int = fun3("100", "10")
    println(res7)

    /**
     * 使用下划线进行占位,那么Scala会自动根据参数类型和返回值类型,创建一个新的相符合的函数
     * 偏函数
     */
    val funn3: String => Int = fun3("100", _)
    val res8: Int = funn3("100")
    println(res8)
    val res9: Int = funn3("1000")
    println(res9)

  }
}

2.13数组

//数组:在内存中一块连续固定大小的空间,有索引可以检索数据,查询快,但是增删速度较慢
//创建一个数组
val arr1: Array[Int] = Array(11, 22, 33, 44, 55)
println(arr1(0))
println(arr1(1))
println(arr1(2))
println(arr1(3))
println(arr1(4))

3、Scala中的”_"的用法总结

在Scala中的大部分情况下,表示所有或者默认值或者占位符的时候,都使用下划线

1、导包时

  • 多引用的方法,和Java中的*类似,相当于该类下面的任意子类
import scala.collection.mutable._

2、在访问元组

  • 和值在一起使用则表示第几个元素
val/var 元组名 = (元素1, 元素2, 元素3....)
//获取第一个元素
元组名._1
//获取第二个元素
元组名._2

3、根据定义的变量的类型的初始值进行的占位符

var gender:String = _

4、使用下划线来简化函数的定义

  • 当函数的参数在函数体中只出现一次,而且函数体没有嵌套调用时,可以使用下划线来简化函数的定义

def main(args: Array[String]): Unit = {
    val a = List(1,2,3,4,5)
//    a.foreach(x=>println(x))
    a.foreach(println(_))
}

5、用于元素匹配,匹配每一个元素

List(1,2,3,4,5,6,7,8,9).filter(_ % 2 == 0)

6、用于替换函数中的参数

  • 函数参数在函数中只出现一次,则可以使用下划线代替

    /**
     * 偏函数
     */
    val f1: String => Int = function1("1", _)
    val res1: Int = f1("1000")
    val res2: Int = f1("2000")
    val res3: Int = f1("3000")
    println(s"res1:$res1,res2:$res2,res3:$res3")

7、用于模式匹配中的默认匹配项

case表达式中的无需使用到的匹配到的变量,可以用下划线代替

变量 match {
  case "常量1" => 表达式1
  case "常量2" => 表达式2
  case "常量3" => 表达式3
  case _ => 表达式4 // 默认匹配项
}


str match {
   case "hadoop" => println("大数据分布式存储和计算框架")
   case "zookeeper" => println("大数据分布式协调服务框架")
   case "spark" => println("大数据分布式内存计算框架")
   case _ => println("未匹配")
  }

在case校验时,变量没有被使用,也可以用下划线替代

  • 下面是Scala中处理异常的时间的使用

      /**
       * 也可以手动的抛出异常
       */
      val sc = new Scanner(System.in)
      print("输入除数:")
      val cs: Int = sc.nextInt()
      if(cs!=0){
        println(10/cs)
      }else{
        throw new ArithmeticException("您输入的除数是0")
      }
    }catch{
      //类似于sql语句中case when
      case e:ArithmeticException=>
//        println("除0异常")
          e.printStackTrace()
      case e:ArrayIndexOutOfBoundsException=>
        println("数组越界异常")
      case _ =>
        println("出现异常")
    }finally {
      //今后finally中的处理大部分情况下都与释放资源有关
      println("这是finally代码块")
    }

8、在定义变量时

  • 在定义变量时,使用下划线占位,就表示将来会赋予该变量默认值
  /**
   * 定义成员变量
   */
  val _name: String = name
  val _age: Int = age
  var _gender: String = _ // 这个下划线,就表示将来会赋予默认值

4、Scala中的集合

List: 元素有序,且可以发生重复,长度是固定的

Set:元素无序,且唯一,长度固定的

Map:元素是以键值对的形式,键是唯一的

Tuple:元组,长度是固定的,每一个元素的数据类型可以是不一样的

4.1ArrayList

object Demo13ArrayList {
  def main(args: Array[String]): Unit = {
    val list1: util.ArrayList[Int] = new util.ArrayList[Int]

    list1.add(11)
    list1.add(123)
    list1.add(22)
    list1.add(31)
    list1.add(17)

    println(list1)

    var i=0
    while (i<list1.size()){
      val res1: Int = list1.get(i)
      println(res1)
      i+=1
    }
  }
}

4.2 List

  • List中的基础用法,和Java中的集合用法一致
//创建一个scala中的List集合
//创建了一个空集合
//    val list1: List[Nothing] = List()
val list2: List[Int] = List(34, 11, 22, 11, 33, 44, 55, 22, 75, 987, 1, 12, 34, 66, 77)

println(list2)
//获取List集合的长度
println(list2.size)
println(list2.length)
println("=" * 50)
//可以直接通过索引下标获取元素
println(list2(0))
println(list2(1))
println(list2(2))
println("=" * 50)
//scala推荐获取第一个元素的方式是调用head函数
println(list2.head)
println(list2.last)
//根据指定的分隔符拼接元素
println(list2.mkString("|"))
println("=" * 50)
val resList1: List[Int] = list2.reverse //返回一个新的集合
println(s"list2:$list2")
println(s"resList1:$resList1")
println("=" * 50)
//对集合中元素进行去重
val resList2: List[Int] = list2.distinct //返回一个新的集合
println(s"list2:$list2")
println(s"resList2:$resList2")
println("=" * 50)
val resList3: List[Int] = list2.tail // 除去第一个,其余的元素返回一个新的集合
println(s"list2:$list2")
println(s"resList3:$resList3")
println("=" * 50)
val resList4: List[Int] = list2.take(5) // 从左向右取元素,取若干个
println(s"list2:$list2")
println(s"resList4:$resList4")
println("=" * 50)
val resList5: List[Int] = list2.takeRight(5) //取右边的几个,组成新的集合
println(s"list2:$list2")
println(s"resList5:$resList5")
println("=" * 50)
//从第一个判断取数据,直到不符合条件停止
val resList10: List[Int] = list2.takeWhile((e: Int) => e % 2 == 0)
println(s"list2:$list2")
println(s"resList10:$resList10")
println("***********************************" * 50)
val res1: Int = list2.sum // 元素必须是数值
println(s"集合中的元素和为:$res1")
println("=" * 50)
val res2: Int = list2.max
println(s"集合中的元素最大值为:$res2")
println("=" * 50)
//集合的遍历
for (e <- list2) {
    println(e)
}
println("=" * 50)
  • Scala中的List高阶函数用法
/**
     * 高阶函数:
     * foreach: 将集合中的元素依次取出传入到后面的函数中
     * 注意:没有返回值的,要么就输出,要么就其他方式处理掉了
     */
//def foreach[U](f: A => U)
//    list2.foreach((e: Int) => println(e))
//    list2.foreach(println)
//需求1:使用foreach求出集合中偶数的和
var ouSum = 0
var jiSum = 0
list2.foreach((e: Int) => {
    if (e % 2 == 0) {
        ouSum += e
    } else {
        jiSum += e
    }
})
println(s"集合中偶数之和为:$ouSum")
println(s"集合中奇数之和为:$jiSum")
println("=" * 50)
/**
     * 高阶函数:
     * map: 依次处理每一个元素,得到一个新的结果,返回到一个新的集合中
     */
val list3: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
//需求2:将集合中的每一个元素*2
val resList6: List[Int] = list3.map((e: Int) => e * 2)
println(s"list3:$list3")
println(s"resList6:$resList6")

/**
     * 高阶函数:
     * filter: 保留符合条件的元素
     */
println("=" * 50)
val list4: List[Int] = List(4, 7, 9, 10, 12, 11, 14, 9, 7)
val resList7: List[Int] = list4.filter((e: Int) => e % 2 == 0)
println(s"list4:$list4")
println(s"resList7:$resList7")

/**
     * 高阶函数:
     * sortBy: 排序
     * sortWith: 两个数之间的关系排序
     */
println("=" * 50)
val resList8: List[Int] = list4.sortBy((e: Int) => -e)
println(s"list4:$list4")
println(s"resList8:$resList8")
val resList9: List[Int] = list4.sortWith((x: Int, y: Int) => x > y)
println(s"list4:$list4")
println(s"resList9:$resList9")

/**
     * 高阶函数:
     * flatMap: 扁平化
     */
println("=" * 50)
val list5: List[String] = List("hello|world|java", "hello|hadoop|flink", "scala|spark|hadoop")
val resTmp1: List[String] = list5.flatMap((e: String) => e.split("\\|"))
resTmp1.foreach(println)

/**
     * 高阶函数:
     * groupBy: 分组
     */
val list6: List[String] = List("hello", "world", "java", "hadoop", "flink", "java", "hadoop", "flink", "flink", "java", "hadoop", "flink", "java", "hadoop", "hello", "world", "java", "hadoop", "hello", "world", "java", "hadoop")
val map: Map[String, List[String]] = list6.groupBy((e: String) => e)
for (e <- map) {
    println(e)
}

/**
     * 基本函数
     *
     * 高阶函数:
     *  foreach: 依次取出元素,进行后面函数逻辑,没有返回值
     *  map: 依次取出元素,进行后面函数逻辑,有返回值,返回新的集合
     *  filter: 所有数据中取出符合条件的元素
     *  sortBy/sortWith: 排序
     *  flatMap: 扁平化
     *  groupBy: 分组,结果是一个map集合
     */

4.3Set

set集合:
	scala中的Set集合也是不可变的,除了排序相关的函数以外,List集合有的高阶函数,Set集合也有
val set1: Set[Int] = Set(1, 4, 3, 6, 5)
val set2: Set[Int] = Set(3, 6, 5, 7, 8)
println(s"$set1")
println(s"$set2")

//    val res1: Set[Int] = set1.&(set2)
//求交集
val res2: Set[Int] = set1 & set2
println(s"$res2")
//求并集
val res3: Set[Int] = set1.|(set2)
println(s"$res3")
//求差集
val res4: Set[Int] = set1.&~(set2)
println(s"$res4")

/**
     * list集合和set集合可以相互转换
     */
val list1: List[Int] = List(11, 22, 33, 44, 55, 11, 22, 44, 88, 33, 44, 99, 11, 22, 55)
val set3: Set[Int] = list1.toSet
println(s"$set3")
val list2: List[Int] = set3.toList.sortBy((e: Int) => e)
println(s"$list2")
posted @ 2024-08-21 16:38  shmil  阅读(11)  评论(0编辑  收藏  举报