Scala WordCount、Scala 集合与 java 集合的相互转换、Scala 模式匹配、隐式转换、偏应用函数、Scala 反射

Scala WordCount

WordCount

groupBy

链式调用

package com.shujia.scala

import java.io.{BufferedReader, FileReader}
import java.util

import scala.io.Source

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

    /**
      *
      * 使用java的方式统计单词的数量
      *
      */

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

    val bufferedReader = new BufferedReader(new FileReader("data/words.txt"))

    var line: String = bufferedReader.readLine()
    
    while (line != null) {
    
      val split: Array[String] = line.split(",")
      
      for (word <- split) {

        //判断map集合中是否存在这个单词
        if (hashMap.containsKey(word)) {
          //取出之前的统计结果
          val count: Integer = hashMap.get(word)
          //在之前的基础上加一
          hashMap.put(word, count + 1)
        } else {
          //如果单词在hashMap中不存在
          hashMap.put(word, 1)
        }
      }
      line = bufferedReader.readLine()
    }

    println(hashMap)

    println("=" * 100)

    /**
      * 使用 scala 统计
      *
      */

    //1、读取文件
    val lines: List[String] = Source.fromFile("data/words.txt").getLines().toList

    //2、将每一行中的多个单词拆分出来,每个单词一行
    val words: List[String] = lines.flatMap(line => line.split(","))

    /**
      *
      * groupBy: 指定一个字段进行分组
      *
      * 返回一个map集合
      * map集合的key 是分组的字段
      * map集合的values是组内所有的元素
      *
      */
    //3、按照单词分组,将同一个单词分到同一个组内
    val groupBy: Map[String, List[String]] = words.groupBy((word: String) => word)

    //4、统计单词的数量
    val wordCount: Map[String, Int] = groupBy.map(kv => {
      //key
      val word: String = kv._1

      //组内所有的单词
      val values: List[String] = kv._2

      //计算单词的数量
      val count: Int = values.length

      //返回结果
      (word, count)
    })

    wordCount.foreach(println)


    println("=" * 100)

    /**
      * 链式调用
      *
      */

    Source.fromFile("data/words.txt")
      .getLines()
      .toList
      .flatMap(_.split(",")) //将一行转换成多行
      .groupBy(w => w) //按照单词分组
      .map(kv => (kv._1, kv._2.length)) //统计单词的数量
      .foreach(println)
  }
}

计算每个班级同学的平均年龄

package com.shujia.scala

import scala.io.Source

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

    /**
      *
      * 统计每一个班级的平均年龄
      *
      */

    //1、读取文件
    val students: List[String] = Source.fromFile("data/students.txt").getLines().toList

    //2、取出班级和年龄
    val clazzAndAge: List[(String, Double)] = students.map(student => {
      //取出班级和年龄
      val split: Array[String] = student.split(",")
      val age: Double = split(2).toDouble
      val clazz: String = split(4)

      (clazz, age)
    })

    //3、按照班级分组
    val groupBy: Map[String, List[(String, Double)]] = clazzAndAge.groupBy(kv => kv._1)

    //4、统计平均年龄
    val clazzAvgAge: Map[String, Double] = groupBy.map(kv => {
      //取出key 班级
      val clazz: String = kv._1

      //取出value 一个班级所有的数据
      val values: List[(String, Double)] = kv._2

      //取出年龄
      val ages: List[Double] = values.map(ca => ca._2)

      //计算年龄平均值
      val avgAge: Double = ages.sum / ages.length

      (clazz, avgAge)
    })

    clazzAvgAge.foreach(println)

  }
}

Scala 集合与 java 集合的相互转换

import scala.collection.JavaConversions._ ---- java → Scala

import scala.collection.JavaConverters._ ---- Scala → java

package com.shujia.scala

import java.util

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

    /**
      * 1、将java的集合转换成scala集合
      */

    val arrayList = new util.ArrayList[Integer]()

    arrayList.add(1)
    arrayList.add(2)
    arrayList.add(3)
    arrayList.add(4)
    arrayList.add(5)

    /**
      * 增强for循环底层使用的是迭代器
      *
      * java集合和scala集合不是同一个迭代器
      * 所以在scala中不能使用增强for循环遍历java集合
      *
      */

    /* for (i <- arrayList) {
       println(i)
     }*/

    /**
      * 将java集合转换成scala的集合
      * import scala.collection.JavaConversions._
      * 这里的 _ 类似于java中 * 的意思
      */

    //导入隐式转换(隐式转换可以动态给对象增加新的方法)
    import scala.collection.JavaConversions._

    val list: List[Integer] = arrayList.toList


    /**
      * 将scala集合转换成java的集合
      * import scala.collection.JavaConverters._
      */

    val list2 = List(1, 2, 3, 4, 5, 6, 7)
    
    import scala.collection.JavaConverters._

    //scala集合转换成java集合
    val javaList: util.List[Int] = list2.asJava
  }
}

Scala 模式匹配

匹配基本数据类型

匹配变量类型

匹配样例类

应用

package com.shujia.scala

import scala.io.Source

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

    /**
      * 模式匹配
      * java 模式匹配 -- switch
      * 可以匹配 基本数据类型 String 枚举
      *
      *
      * scala的模式匹配 -- match
      * 可以匹配 基本数据类型 字符串 枚举 类型匹配 样例类
      *
      */

    //1、匹配基本数据类型

    val i = 100

    /**
      * match : 按照从上往下的顺序匹配,匹配成功之后跳出 match
      *
      */

    i match {
      case 100 => println("100")
      case 200 => println("200")
      //匹配其它情况 这里的 _ : 通配符
      case _ => println("其它")
    }

    //模式匹配可以有返回值
    //变量i 奇数加一 偶数乘2
    val j: Int = i % 2 match {
      case 1 => i + 1
      case 0 => i * 2
    }

    println(j)

    //2、匹配变量类型

    var str: Any = 12312.0

    //被匹配的类型只能是变量类型的子类型
    str match {
      case s: String => println(s"字符串类型:$s")
      case i: Int => println(s"Int类型:$i")
      case _ => println(s"其它类型:$str")
    }

    //3、匹配样例类
    case class User(id: String, name: String)

    val user = User("004", "张三")

    user match {
      case User("001", "张三") => println("张三")
      case User("002", "李四") => println("李四")
      case User("003", "王五") => println("王五")
      case i: User => println(i)
      case _ => println("其它")
    }


    /**
      * 应用
      *
      */

    val list = List(("001", "张三", 23), ("002", "李四", 24), ("003", "王五", 25))

    val list2: List[(String, String, Int)] = list.map(kv => {
      val id: String = kv._1
      val name: String = kv._2
      val age: Int = kv._3
      (id, name, age + 1)
    })

    list2.foreach(println)

    //简写
    val list3: List[(String, String, Int)] = list.map {
      case (id: String, name: String, age: Int) => {
        (id, name, age + 1)
      }
    }

    list3.foreach(println)

    println("=" * 100)

    val students: List[String] = Source.fromFile("data/students.txt").getLines().toList

    val list4: List[Array[String]] = students.map(student => student.split(","))

    //匹配数组
    val clazzAndAge: List[(String, String)] = list4.map {
      case Array(id: String, name: String, age: String, gender: String, clazz: String) => {

        (clazz, age)
      }
    }

    clazzAndAge.foreach(println)
  }
}

Map集合 getOrElse 底层原理 -- 模式匹配

package com.shujia.scala

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

    val map = Map("001" -> "张三", "002" -> "李四")

    val name: String = map.getOrElse("001", "王五")

    println(name)

    /**
      * getOrElse 底层原理 -- 模式匹配
      * Option: 是一个可选的值 (有值:Some , 没有值:None)
      */

    val option: Option[String] = map.get("005")

    val value: String = option match {
      case Some(v) => v
      case None => "默认值"
    }
  }
}

隐式转换

隐式转换 -- 隐式类型转换

显示转换 -- 显示类型转换

implicit -- 定义隐式转换的关键字

1、隐式转换方法

package com.shujia.scala

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


    /**
      * 隐式转换  --  隐式类型转换
      * 显示转换  --  显示类型转换
      *
      */

    //1、显示转换
    val s = "100"
    val i: Int = s.toInt


    def print(s: String): Unit = {
      println(s)
    }

    print("java")
    
    //显示转换
    print(100.toString)

    /**
      * implicit -- 定义隐式转换的关键字   
      * 
      * 1、隐式转换方法
      * 
      * 隐式转换只在当前作用域中起作用
      *
      * 隐式转换方法:可以 隐式的 将 该作用域中变量的类型 转换成 隐式转换方法的返回值类型
      *
      * 通过 参数类型、返回值类型 唯一标识一个隐式转换方法
      *
      * 在同一个作用域中不能存在 参数类型和返回值类型一样的 隐式转换方法
      *
      * 符合隐式转换条件的 变量 在被调用的时候,默认只能使用一次符合的隐式转换方法
      * 比如说:在同一个作用域中有两个隐式转换方法 A:int→double B:double→string 
      * 变量 C 为 int 类型 ,将它传入一个参数类型为 string 的函数中是会报错的,因为 C 不能先隐式调用A再隐式调用B
      * 
      */
    implicit def intToString(i: Int): String = {

      println("隐式转换方法被调用")

      i.toString
    }

    implicit def intToDouble(i: Int): Double = {

      println("隐式转换方法被调用")

      i.toDouble
    }


    implicit def doubleToString(i: Double): String = {

      println("隐式转换方法被调用")

      i.toString
    }

    /**
      *
      * 在执行的时候会隐式的将Int转换成String类型
      * 隐式调用上面的intToString方法
      * 就意味着在当前作用域中 int类型可以被当做string来使用
      *
      */
    print(1000)

    print(100.0123)

  }
}

隐式转换类

package com.shujia.scala

import scala.io.Source

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

    /**
      * 隐式转换类
      *
      */
    
    // 隐式转换类 还是可以通过 new 对象 来使用类中方法的
    val fileRead = new FileRead("data/students.txt")
    val student: List[String] = fileRead.read()

    println(student)

    /**
      * String 类型被隐式转换成了FIleRead 类型,所以String 有了Read方法
      */
    val path = "data/students.txt"
    val list: List[String] = path.read()

    val words: List[String] = "data/words.txt".read()

  }

  /**
    * 隐式转换类可以隐式的将类的构造函数所需参数的类型转换成当前类的类型
    *
    * 隐式转换类需要被定义在 object 中
    *
    * String  -- 隐式转换-->   FileRead
    */
  implicit class FileRead(path: String) {
    def read(): List[String] = {
      Source.fromFile(path).getLines().toList
    }
  }
}

隐式转换参数 和 隐式转换变量

函数柯里化

package com.shujia.scala

import scala.io.{BufferedSource, Codec, Source}

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

    /**
      * 隐式转换参数
      * 可以简化方法调用
      */
      
    //函数柯里化
    //(implicit y: Int) -- 隐式转换参数
    def add(x: Int)(implicit y: Int): Int = {
      x + y
    }

    println(add(1)(2))

    //隐式转换变量
    //同一作用域中不能出现两个类型一样的隐式转换变量
    implicit val i: Int = 100
    //在调用方法的时候会自动使用当前作用域中的隐式转换变量填充方法的隐式转换参数,类型要一致
    println(add(300))


    //应用
    //(Codec("utf-8")) -- 其实不需要我们手动指定,Scala已经默认通过隐式转换加上了
    val source: BufferedSource = Source.fromFile("data/students.txt")(Codec("utf-8"))

  }
}

偏应用函数

package com.shujia.scala

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


    def fun(x: Int, y: Int): Int = {
      x + y
    }

    println(fun(1, 2))

    /**
      * 偏应用函数
      * 可以先向函数中传一部分参数,会返回一个函数
      * 之后可以向返回的函数中 传入 多个不一样的参数
      */
    val function: Int => Int = fun(100, _: Int)

    println(function(100))
    println(function(200))
    println(function(300))
    println(function(400))
  }
}

Scala 反射

package com.shujia.scala

object Demo33Class {
  def main(args: Array[String]): Unit = {
    /**
      * 反射 : 通过类对象来创建类的对象
      *
      * 类对象:class文件在JVM中的存在形式
      * 所有的 .class文件 被加载到JVM中的时候,都是以Class对象的形式存在的
      *
      * 类的对象:通过new出来的对象
      *
      * 类对象的作用
      * 1、可以通过类对象获取类的构造函数 --- 可以通过这个构造函数创建类的对象(反射)
      * 2、可以通过类对象获取类的方法,属性,注解
      *
      * Class类是java中第一个被加载的类
      */

    //获取类对象
    //1、通过Class获取
    val stuClass: Class[_] = Class.forName("com.shujia.scala.Demo34Student")

    //2、通过类名获取
    val stuClass2: Class[Demo34Student] = classOf[Demo34Student]

    //3、通过类的对象获取类对象
    val student = new Demo34Student("001")
    val stuClass3: Class[_ <: Class[_]] = stuClass.getClass
  }
}

// java类
package com.shujia.scala;

public class Demo34Student {
    private String id;


    public Demo34Student() {
    }

    public Demo34Student(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Demo34Student{" +
                "id='" + id + '\'' +
                '}';
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}
posted @ 2022-03-05 22:56  赤兔胭脂小吕布  阅读(35)  评论(0编辑  收藏  举报